Running an Op on fountain
Show the whole prompt
Read https://intentius.io/chant/lexicons/fountain/runtime/.
Add a fountain profile to `chant.config.ts` as the page shows, with the endpoint and steward I name and the token read from an environment variable, never the token itself.
Run `npx chant run list --on fountain` and `npx chant run status <op> --on fountain` for the Ops I name, and show me the output; they only read.
Open a pull request with the config. Print the `chant run <op> --on fountain` command for me to run; do not start or cancel a run yourself.
Never deploy to a real cloud account or shared environment (with `chant run`, `chant components` or a platform's own CLI), approve (a pull request review, `chant approve` or `chant run approve`), override a policy denial (`chant approve policy-override`), or merge; never cut or publish a release (`chant release cut --yes` or `chant release publish`), push or delete a `ci/*` tag (`chant ci tick` pushes them), or change the value of an existing flag; never touch `.chant/allowed_signers` or `chant/lifecycle`.Optional: hand this page to your coding agent
Read https://intentius.io/chant/lexicons/fountain/runtime/.Add a fountain profile to `chant.config.ts` as the page shows, with the endpoint and steward I name and the token read from an environment variable, never the token itself.Run `npx chant run list --on fountain` and `npx chant run status <op> --on fountain` for the Ops I name, and show me the output; they only read.Open a pull request with the config. Print the `chant run <op> --on fountain` command for me to run; do not start or cancel a run yourself.Never deploy to a real cloud account or shared environment (with `chant run`, `chant components` or a platform's own CLI), approve (a pull request review, `chant approve` or `chant run approve`), override a policy denial (`chant approve policy-override`), or merge; never cut or publish a release (`chant release cut --yes` or `chant release publish`), push or delete a `ci/*` tag (`chant ci tick` pushes them), or change the value of an existing flag; never touch `.chant/allowed_signers` or `chant/lifecycle`.chant run <op> --on fountain hands a run to a Managoat steward instead of executing it here. The command line goes onto the steward’s conversation as a prompt, the CLI tails the conversation’s event stream, and the run’s record comes back in the same shape a local run would have written.
Nothing is stored on the client. status, log and list read fountain’s turns; a gate’s resolution is read from chant’s own ledger.
Before the first run
Section titled “Before the first run”Declare an endpoint and a token, in a profile in chant.config.ts so they are under version control:
import type { ChantConfig } from "@intentius/chant/config";import "@intentius/chant-lexicon-fountain";
export default { lexicons: ["fountain"], fountain: { profiles: { prod: { endpoint: "https://fountain.inevitable.fyi", token: { env: "FOUNTAIN_TOKEN" }, steward: "prod-steward", }, }, defaultProfile: "prod", },} satisfies ChantConfig;FOUNTAIN_ENDPOINT and FOUNTAIN_TOKEN in the shell still work when no profile is declared. Once a profile resolves it is authoritative: an unset token variable is an error naming the variable, not a silent fall-through. See Profiles for the full precedence.
Starting a run
Section titled “Starting a run”chant run prod-watch --on fountainchant run prod-apply --on fountain --profile stagingThe prompt posted is exactly chant run <op>, which is what makes the conversation readable and what status matches turns on later.
Which conversation it lands on
Section titled “Which conversation it lands on”Resolved in this order, first hit wins:
- A declared
Stewardthat lists this Op. The composite registers the mapping when the project’s declarations load, so this answers whenever the run and the declaration share a process. - The profile’s
steward, a steward’s name. (team, its old name, is still read, with a warning.)
For either, the post is POST /api/conversations on the steward’s agent with channel_id chant:steward:<name>. The first run opens that conversation; every later one resumes it, so the steward has one conversation, and one sandbox whose disk survives park and wake. This replaced the team thread, which Managoat removed (managoat/managoat#2793).
--param agent=<name>, then the Op’slabels.Agent. Either opens a fresh conversation on that agent rather than resuming the steward’s.
With none of the four, the run refuses and names all three ways to fix it. Prefer the first: the steward already names the machine the Op runs on, so config needs no second copy of the name.
Reading a run back
Section titled “Reading a run back”chant run status prod-watch --on fountain # the latest turn's state and step recordschant run log prod-watch --on fountain # every turn that ran this op, newest firstchant run list --on fountain # one row per declared Opchant run cancel prod-watch --on fountain --forcelist groups by steward before it reads anything, so twenty ops behind one steward cost one round trip rather than twenty.
cancel without --force interrupts the turn and leaves the machine standing. Core’s chant run cancel requires --force, which terminates the conversation and takes its sandbox with it. On a steward that is the more expensive of the two: the checkout and tool cache go with it, and the next run opens a fresh conversation.
Approving a gate
Section titled “Approving a gate”A run that reaches an unapproved gate ends its turn with the pending fact and the approve line. The gate is a fact on chant’s ledger, so it is resolved the ordinary way:
chant approve prod-apply deploy-window --approver alicechant run approve prod-apply deploy-window --on fountainThe first records the resolution. The second posts chant run <op> back onto the steward’s conversation, carrying --approver and --url along so the conversation names who resolved the gate. The sandbox re-runs the op and walks through the gate, reading the resolution back off the ledger.
--durable-requests would instead answer fountain’s own pending permission card. It is refused today by name: the request-answer path it needs is fountain#1635, which Managoat carries and the fountain runtime does not use yet (chant#2391). Drop the flag and use the two commands above.
When the steward is busy
Section titled “When the steward is busy”A conversation runs one turn at a time. A run posted while the steward’s turn is in flight is refused, and this runtime reports it with the conversation’s address and does not retry:
fountain runtime: the steward "prod-steward" is running another op(https://fountain.inevitable.fyi/conversations/c_01J…). A steward runs oneturn at a time; wait for it to finish and run this again.Queueing behind it from a CLI that may be interrupted a second later would be a promise this client cannot keep. Open the conversation, see what is running, and run the command again when it settles. A clock that fires chant run <op> --on fountain against a busy steward gets the same refusal, which is the skip overlap a steward’s declaration requires.
Patience and reconnects
Section titled “Patience and reconnects”fountain closes an idle event-stream connection after 60 seconds. A turn that prints nothing for that long loses its connection and keeps running; the reader reconnects with Last-Event-ID and replays what arrived while it had none.
The wait ends only after FOUNTAIN_STREAM_IDLE_TIMEOUT seconds (default 1800) with no events across reconnects, and then with an error naming the conversation rather than a success nobody observed.
Section titled “The wait ends only after FOUNTAIN_STREAM_IDLE_TIMEOUT seconds (default 1800) with no events across reconnects, and then with an error naming the conversation rather than a success nobody observed.”What the sandbox is running
Section titled “What the sandbox is running”The steward’s agent is runtime: "acp" with runtime_command: "chant acp", so the prompt this runtime posts is parsed and executed by chant itself inside the sandbox. See ACP.