writes: delegated Adopt — foreign node → ReconcileOp → PR (#8) - #16
Merged
Merged
Conversation
The cloud→code gesture. A *foreign* node (provisioned, not declared) can be pulled back into typed source: Adopt triggers the project's ReconcileOp, which opens a reviewable PR. behold never writes source — a human merges. - src/adopt.ts: `isAdoptable(node)` (foreign + live-import lexicon) and `extractPrUrl(line)` (pull the opened PR/MR URL out of the now-line). The live-import lexicon set (aws/azure/gcp/k8s) is the server's source of truth. - server: /api/ops returns `adoptLexicons`; the run stream lifts a PR URL to a `pr` SSE event (chant #841 surfaces it as a ReconcileOp outcome). - web: Adopt moves from the global bar to the inspect panel, shown only on an adoptable node; a `pr` event links the opened PR in the now-line and pins it in the header. tsc clean; 26 tests pass (+6 adopt).
lex00
added a commit
that referenced
this pull request
Jul 19, 2026
…e-around) Two gaps around apply on a local emulator that can't idempotently re-apply (github.com/lex00/floci/issues/16 — stack update re-creates fixed-name resources → 'already exists' → rollback): - The apply picker was a bare name list — no way to tell which stacks are already applied. Annotate each option with live status (✓ deployed / ⚠ rolled back / ○ not deployed), from the same stack-status seam the graph paints. - apply-all blindly re-applied everything (collides on Floci). Make it status- aware: no-op when all are healthy+in-sync; call out rolled-back stacks that a re-apply won't recover; and add a 'Reset' button on the Floci substrate pill → POST /api/local/reset (local-down + local-up) for a clean slate, then apply lands all-creates. The honest recovery, since the emulator can't re-apply. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
lex00
added a commit
that referenced
this pull request
Jul 19, 2026
…after local-up.sh boots the emulator AND deploys (its 'provision infra on Floci' step), so 'reset' is a full clean reset+redeploy, not just an empty reboot. Telling the user to apply afterward was wrong — that re-apply is exactly the collision Floci #16 describes. Reword: reset reboots + redeploys clean, no apply needed. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
lex00
added a commit
that referenced
this pull request
Jul 19, 2026
A blind 'apply all' over a green deploy silently re-broke loom-db/frontend:
Floci re-creates their fixed-name resources on update ('... already exists') and
rolls the stack back (#16). Nothing stopped the re-apply — the header no-op only
covered the all-healthy case, and the picker path skipped it entirely.
Guard /api/apply server-side (covers every client path + stray calls): a
component with any live stack (good/warn/accent, not 'neutral') is already
deployed → 409 with a message pointing at Reset (the only clean redeploy on an
emulator that can't re-apply). ?force=1 overrides. Best-effort — a status-check
error falls through so a legitimate fresh apply isn't blocked.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
lex00
added a commit
that referenced
this pull request
Aug 7, 2026
…s, honest component status (#159) Verified against a live kubemicrovm-ops (k3d + floci, tier prod-ha) and fountain-ops. Five gaps, one theme: what the estate actually runs was invisible or wrongly painted. - Component status: an ABSENT deploy unit (`stack: {name}` — no status, no healthy) painted accent as if mid-deploy, outranking its own all-present rollup; five of kubemicrovm's seven components read "in flux" on a green estate. Only `healthy: false` decides now; absence falls through to the rollup. - The cluster build root: the estates declare their k3d cluster as chant source in `cluster/`, deliberately outside sourceDir, so no view ever saw it — the k8s half rendered inside a synthetic `cluster <env>` box. `clusterRootGraphIr` reads that root the way the estates' own justfiles do; the merged K3d::Cluster is painted from `k3d cluster list` (running → good, declared-but-absent → accent) and becomes the cluster box. - Cluster anchoring: `K3d::Cluster` joins MANAGED_CLUSTER_KINDS, and the bound kube context (k8s.profiles.<env>.context — the dead-code contextBindsCluster, finally wired, now k3d-aware) breaks the multi- cluster tie, so fountain-ops's two declared clusters anchor to the one the reads actually land on instead of declining. - Helm releases: a deploy-step estate (helm-upgrade units, no declared Helm::Chart nodes) observed its releases and had nothing to hang them on — helm was invisible on every zoom. Observed releases matching no declared chart synthesize as Helm::Release nodes: component-owned ones (release names scraped from *.component.ts, the same convention ops.ts uses) good/warn by helm status, the rest warn (foreign). The logical view places them in their namespace boxes, creating the box under the cluster for an observed-but-undeclared namespace. applyHelmArtifacts + the synthesis + the wrong-tier note now also run on /api/refresh and the logical overlay branch, which silently dropped them. - Substrates: the Floci probe accepts `chant-floci` (chant emulator up's container name) alongside `floci`; the Helm pill reports the PROJECT'S bound context instead of the ambient current-context (observed live: an estate bound to k3d-kubemicrovm-local whose pill named a real EKS cluster); the /api/apply Floci #16 pre-flight only fires when applies actually target Floci — on a k8s/helm estate a re-apply is the normal sync gesture and used to 409 with an error naming an emulator the project doesn't use. pinhole ^0.2.5: reserved `_`-attrs stay off cards (no more `_status: good` printed on every overlay card), childless containers lay out finite, and group boxes carry the container node's status tint. Claude-Session: https://claude.ai/code/session_01NEtbXBSwLiYFMKv2o4VMb4 Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
lex00
added a commit
that referenced
this pull request
Aug 7, 2026
… no phantom docs (#160) Moving every write into the ⌘K palette (#73) left the header with zero action buttons: behold looked read-only unless you happened to press ⌘K, the docs still said "click Run floci-apply" about buttons that no longer existed, and an estate had three differently-named routes to the same apply. Concretely: - The PRIMARY deploy gesture is a header button again. A committed ApplyOp gets `▶ Deploy (<op>)` (+ `Approve <gate>` beside it when gated); a project with only components gets `▶ Deploy…`, which opens the dial's component picker. One intent, one word — the tooltip carries the mechanism. Everything else stays in ⌘K. - The dial no longer vanishes wordlessly when no env is picked — it says what's missing and where to pick it. A static export keeps the silence (there is genuinely nothing to offer). - Errors get a toast at the point of gesture, not only a line in a bottom log pane that is display:none until something writes to it. Successes toast too ("running <op> — output streams in the log below"), so a palette action no longer closes into dead air. - The Floci #16 warnings (re-apply collides on the emulator) only appear when the estate actually targets Floci — a k3d/helm estate used to be warned about an emulator it doesn't use, in dialogs and in the 409 (the server side of this gating landed in #159). - Docs describe the UI that exists: README, example-k8s/README, run-it.mdx, and acting.mdx's action table (button vs palette, per action). Claude-Session: https://claude.ai/code/session_01NEtbXBSwLiYFMKv2o4VMb4 Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #8.
The second write gesture — cloud→code. A foreign node (provisioned, not declared) is pulled back into typed source: Adopt triggers the project's
ReconcileOp, which regenerates the source and opens a reviewable PR. behold never writes source directly — a human merges the PR.Mechanism
src/adopt.ts(unit-tested):isAdoptable(node)— foreign (_status === "foreign") and on a live-import lexicon.extractPrUrl(line)— pull a GitHub/GitLab PR/MR URL out of an Op output line.LIVE_IMPORT_LEXICONS = [aws, azure, gcp, k8s]— the substrates with a cloud→code path; the server's source of truth./api/opsnow returnsadoptLexicons; thechant runstream lifts a PR URL to aprSSE event.prevent links the opened PR in the now-line and pins a "PR opened →" link in the header.Depends on chant #841 (PR INTENTIUS/chant#842)
ReconcileOpnow surfaces the opened PR URL as an outcome ([outcome] PR=…), whichextractPrUrlreads from the now-line. The example's^0.18.4caret picks up that fix once chant 0.18.5 publishes.Verified
tsc --noEmitclean; 26 tests pass (+6 adopt: eligibility across managed/foreign/pending × live/non-live lexicons, and PR/MR URL extraction).Acceptance (#8)
ReconcileOpand surfaces the resulting PR link