foldrun 0.6.0 → 0.7.2

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.
@@ -0,0 +1,155 @@
1
+ # Troubleshooting
2
+
3
+ The failures people actually hit, what the platform is telling you, and the
4
+ fix. Every one of these leaves its reason in the run's events; read those
5
+ before anything else.
6
+
7
+ ## When a provider says no
8
+
9
+ The status code decides what happens next, and the runtime already acts on
10
+ the difference:
11
+
12
+ | code | what it means | what the runtime does |
13
+ |---|---|---|
14
+ | **400** | the request is malformed | fails the step — retrying sends the same thing |
15
+ | **401 / 403** | not signed in, or not allowed | tries the fallback provider if one is declared |
16
+ | **402** | out of credit | fallback provider; often a reservation against a large token ceiling rather than an empty account |
17
+ | **404** | no such model or path | fails; usually a base_url with the wrong `format:` |
18
+ | **422** | understood and refused | fails, with the reason in the step's output |
19
+ | **429** | too many requests | **waits and asks again** — up to three times, 2s / 4s / 8s with jitter, honouring a `retry-after` the provider names, on the same key. A 429 that mentions quota, credit or billing is the account, not the traffic, and goes to the fallback instead |
20
+ | **500 / 502 / 503 / 529** | broken or busy at their end | same wait-and-retry as 429 |
21
+
22
+ Every wait is a line in the run log (`provider busy … waiting 3.4s, attempt
23
+ 1 of 3`), so a slow run reads as slow rather than mysterious. Only after the
24
+ retries are spent is the fallback provider tried.
25
+
26
+ ## "verify … → no match"
27
+
28
+ The step's `verify: matches:` or `contains:` did not find its text in what
29
+ the agent concluded. The check reads the step's **final reply**, and its
30
+ first line is the run's headline — so a reporter that opened with "Done."
31
+ and put the verdict on line three fails a `^BAD` check with the right
32
+ verdict sitting there. Tell the agent the first line *is* the verdict, and
33
+ move a step that cannot manage it to a stronger tier.
34
+
35
+ ## "each: the previous group produced no items"
36
+
37
+ `each: lines` splits what the previous step concluded into lines and found
38
+ none. Usually the step wrote its list to a file and replied with a sentence.
39
+ Either have it reply with the list, or use `each: rows of <file>` — a file
40
+ has no turns and is the better contract for a list that must arrive exactly.
41
+
42
+ ## "over budget — $x spent of the flow's $y"
43
+
44
+ The run crossed its `budget:` between two groups; the remaining steps were
45
+ skipped. Look at which step spent it: a fast-tier agent writing a file one
46
+ line per call, re-sending its whole context each time, is the usual culprit.
47
+ Put `model:` on that step, tell the agent to write each file once, and set
48
+ the cap at two or three times a normal run so real work never trips it.
49
+
50
+ ## "over budget — nothing left to spend before this step (budget: on the … agent)"
51
+
52
+ The agent's own `budget:` — the most it may spend in one run — was used up
53
+ by its earlier steps in this run, so this one was refused before it started.
54
+ Raise the number in that agent's `agent.md`, or take it out: unset is no
55
+ limit. The same line with `budget: in the flow file` is the flow's cap and
56
+ lives there instead.
57
+
58
+ ## "is at its budget — $x spent today of $y/day"
59
+
60
+ A cap over time, reached. New runs refuse until the window turns — tomorrow,
61
+ next week, the new month — in the account's own `timezone:`. Raise it in
62
+ Settings or in the file, or remove the line.
63
+
64
+ ## "was denied: … is outside this workspace"
65
+
66
+ The agent reached for a path outside its workspace — `/tmp/something`, an
67
+ absolute path, a checkout a tool made — and was refused. The message names
68
+ the path it probably meant. It costs a turn, nothing more; if one step
69
+ collects many, name the exact path in its prompt (`workspace/storage/x.md`).
70
+
71
+ ## "this push is not live yet — runs in flight"
72
+
73
+ The push was accepted and will apply when the runs finish. A run parked at
74
+ an approval gate counts. Decide the gate, or wait; `foldrun deploy --force`
75
+ applies over a running flow when you mean it.
76
+
77
+ ## "missing `type:` — OKF requires a non-empty type on every concept"
78
+
79
+ A file under `knowledge/` has no `type:` in its frontmatter. Add one
80
+ (`type: Reference` is fine for a table or a list); the push is refused
81
+ until it is there.
82
+
83
+ ## The run is parked and nobody knows
84
+
85
+ Check the account's `notify:` — a workspace that declared its own block
86
+ replaced the account's whole, and may have dropped `awaiting-approval`. The
87
+ dashboard banner shows every parked run across workspaces regardless.
88
+
89
+ ## It ran on the wrong model
90
+
91
+ `model:` resolves nearest-wins: the step, then the flow, then the agent. A
92
+ flow with `model: fast` in its frontmatter runs every step on the fast tier
93
+ whatever each agent says. The run trace names which level won
94
+ (`model: haiku — flow`). Put `model:` on the step to lift one.
95
+
96
+ ## The schedule fired more often than it should
97
+
98
+ When day-of-month and day-of-week are both restricted, cron ORs them.
99
+ `0 5 1-7 * 5` fires every Friday and every day of the first week. Use a
100
+ plain day of month for a monthly job.
101
+
102
+ ## Approval emails have no links
103
+
104
+ The install has no `FOLDRUN_PUBLIC_URL`, or it points at an address that no
105
+ longer resolves. The worker logs why, once. Set it to the origin people
106
+ actually reach the install on.
107
+
108
+ ## A step's file never appeared in Storage
109
+
110
+ The agent wrote to `outputs/` (the run's scratch, archived with the run) or
111
+ to a path relative to somewhere it was not. Deliverables go to
112
+ `workspace/storage/`; the run page's Out column shows what actually landed
113
+ and where.
114
+
115
+ ## The browser came back with `[page rendered empty]`
116
+
117
+ The page loaded, but nothing was on it — and the reason is in the same run
118
+ log, one line above `page: <url>`: `page errors:` (an uncaught error in the
119
+ page's own script), `page console:` (what it logged as an error),
120
+ `requests failed:` (a script or an API call that never landed) or
121
+ `requests refused:` (one the server answered 4xx/5xx). A single-page app
122
+ that renders after load usually shows as none of these — give it a
123
+ `wait_for` selector. A blocked resource you asked to `block` is never
124
+ counted. For the whole picture, call again with `mode: network`: the page's
125
+ own status and redirect chain first, then every request it made.
126
+
127
+ ## A browser action on `"@e4"` failed
128
+
129
+ The number came from the last `mode=aria` in the same `session`, and the
130
+ next call loaded the page fresh, so the tool looked for what the number
131
+ pointed at — its role and name — and the message says which of three things
132
+ happened:
133
+
134
+ - `nothing is numbered yet` — no `mode=aria` ran in this `session` first,
135
+ or it ran under a different `session` name. The numbers are per session.
136
+ - `is not on the page now` — the element is gone: a different page, a
137
+ signed-out view, a list that changed. Read it again with `mode=aria`.
138
+ - `the page has 3 of those now and had 2` — the same button appears a
139
+ different number of times than when it was numbered, so which one was
140
+ meant is a guess the tool will not make. Read it again with `mode=aria`.
141
+
142
+ In each case the fix is the same: take a fresh `mode=aria`
143
+ (`interactive=true` for just the controls) and use its numbers. An element
144
+ with no role and no text — a bare wrapper — cannot be found again at all;
145
+ use a CSS selector for it.
146
+
147
+ ## The browser's output was cut at 18,000 characters
148
+
149
+ The cap is on what the model sees, not on what was kept. `mode: markdown`
150
+ writes all of it to `outputs/page.md`, `meta` to `outputs/meta.json`,
151
+ `table` to `outputs/tables.json`, `network` to `outputs/network.json`, an
152
+ `extract` step to `outputs/extracted.json` — the truncation line names the
153
+ file. Read the file in the next step, or narrow the call: `wait_for` a
154
+ specific section, `block="image,font,media"` so the page is text, or an
155
+ `extract` step whose rows are exactly what you wanted.
@@ -0,0 +1,79 @@
1
+ # Versions and releases
2
+
3
+ The hosted platform deploys itself whenever its code changes — there is no
4
+ release train and nobody decides "this is a release". Every deploy that comes
5
+ up healthy is one, and gets a name.
6
+
7
+ ## The scheme
8
+
9
+ ```
10
+ v2026.10.01.3
11
+ │ │ │ └─ the third deploy that day
12
+ │ │ └──── day (UTC)
13
+ │ └─────── month
14
+ └──────────── year
15
+ ```
16
+
17
+ CalVer with a daily counter, not semver. A box that ships every push to main
18
+ would have a bot bumping a patch number forever, and the numbers would mean
19
+ nothing; a date says when, and sorts. A rollback redeploys an older version
20
+ under its own name — `v2026.09.30.2` deployed again is still `v2026.09.30.2`.
21
+
22
+ Behind each name are the commits of the parts that make up the platform —
23
+ `core` (the runtime), `platform` (queue, worker, storage, billing), `web` (the
24
+ dashboard and the API), `docs` and `infra` — recorded when it was deployed.
25
+ The `foldrun` CLI and `@foldrun/core` on npm are packages a person publishes,
26
+ and keep ordinary semver (`0.6.0`).
27
+
28
+ ## Where to see it
29
+
30
+ | Where | What |
31
+ |---|---|
32
+ | The sidebar's foot | `foldrun v2026.10.01.3`, linking to What's new |
33
+ | **What's new** (`/dashboard/whats-new`) | every recent release, newest first, with what changed in each — grouped Features, Fixes, Docs and Other |
34
+ | **Settings → About** | the version, when it was released, the API version, and each component's commit |
35
+ | `GET /api/version` | the same as JSON, no key needed — see the [API reference](api#versions) |
36
+ | `GET /api/changelog` | the release notes as JSON, with a key |
37
+ | Any `/api` response | the `X-Foldrun-Version`, `X-Foldrun-Api` and `X-Foldrun-Cli` headers |
38
+ | `foldrun version` | this CLI, its core, and the platform it talks to |
39
+
40
+ An open dashboard tab checks every few minutes, and when you come back to it,
41
+ whether the platform has moved on. If it has, a small notice offers a reload
42
+ and a link to What's new. It never reloads by itself.
43
+
44
+ ## Release notes
45
+
46
+ The deploy writes them: for each release, the commits between the version
47
+ before and this one, in every part, grouped from what each commit says —
48
+ Features, Fixes, Docs (anything in the docs, or that says it is docs) and
49
+ Other (dependencies, tests, the deploy's own plumbing). The groups are read
50
+ from the words of a commit subject, so a fix described without the word may
51
+ land under Features. A release whose changes could not be read says so
52
+ rather than showing an empty list.
53
+
54
+ A self-hosted or locally built install has no notes and reports `dev`, or
55
+ whatever `FOLDRUN_VERSION` it was started with.
56
+
57
+ ## The API version
58
+
59
+ `api` in `/api/version`, and the `X-Foldrun-Api` header, is a date —
60
+ `2026-10-01` — that changes only when a route changes in a way an existing
61
+ caller would break on. A new route or a new field in an answer does not move
62
+ it. Breaking changes are announced in the release notes of the version that
63
+ makes them.
64
+
65
+ ## CLI compatibility
66
+
67
+ The CLI talks to the platform over the same HTTP API as everything else, so
68
+ an older CLI keeps working against a newer platform; what it lacks are the
69
+ newest commands. Each platform version records the CLI released with it
70
+ (`packages.cli` in `/api/version`, and `X-Foldrun-Cli` on every response):
71
+
72
+ - `foldrun version` compares that with its own version and warns when the
73
+ platform's is newer.
74
+ - Any other command that reaches the platform prints one dim line when the
75
+ platform's CLI is newer — at most once a day, only in a terminal, and
76
+ never in a script or CI. `FOLDRUN_NO_UPDATE_NOTICE=1` turns it off.
77
+ - `foldrun --version` prints the CLI's version and nothing else, offline.
78
+
79
+ To update: `npm i -g foldrun@latest`.
@@ -0,0 +1,160 @@
1
+ # Workspaces
2
+
3
+ A workspace is a folder, and the folder is the unit of everything: it is what
4
+ you edit, deploy, permission, budget and back up. An account holds several —
5
+ one per job, in practice — and they share nothing unless it is put in the
6
+ account's library on purpose.
7
+
8
+ ## The layout
9
+
10
+ ```
11
+ my-desk/
12
+ AGENTS.md context every agent here sees, and the workspace's defaults
13
+ agents/<name>/ one folder per role
14
+ agent.md frontmatter, then the prompt
15
+ knowledge/ given to this agent only
16
+ memory/ what this agent learned
17
+ outputs/ this step's scratch — archived with the run
18
+ scripts/ code this agent's tools run
19
+ flows/<name>.md a numbered list of steps
20
+ tools/<name>.md what may be called — an API, a script, an MCP server
21
+ skills/<name>/ a capability, in the open Agent Skills format
22
+ evals/<name>.md tests
23
+ knowledge/ given to every agent in the workspace
24
+ memory/ what they learned, shared
25
+ state/ what the next run needs from this one
26
+ storage/ files a person reads or downloads
27
+ scripts/ code shared by this workspace's tools
28
+ ```
29
+
30
+ Every one of those is optional except `AGENTS.md` and at least one agent.
31
+
32
+ ## The account around it
33
+
34
+ On the platform a workspace never stands alone: it lives under an account,
35
+ beside the account's own `AGENTS.md` and the library every workspace there
36
+ shares.
37
+
38
+ ```
39
+ my-account/
40
+ AGENTS.md config and context every workspace here inherits
41
+ library/ tools, skills, scripts, knowledge, memory — shared
42
+ workspaces/
43
+ my-desk/ the tree above
44
+ ads-desk/
45
+ ```
46
+
47
+ `foldrun init` makes exactly that on a laptop, and `foldrun new <name>` adds
48
+ another workspace to it, so the folder you edit is the folder that runs. See
49
+ [the CLI reference](cli#the-shape-of-a-folder) for the commands that act on the
50
+ whole account — `check`, `deploy`, `pull`, `status`, `workspaces` — and for the
51
+ one scope that has no API: the account's own `AGENTS.md` is not pushed or
52
+ pulled, only edited in Settings.
53
+
54
+ A single folder with `agents/` and `flows/` at its root is still a workspace
55
+ and still works everywhere; `foldrun init --flat` makes one.
56
+
57
+ ## `AGENTS.md` — context and defaults
58
+
59
+ The body is prose every agent in the workspace sees before its own prompt.
60
+ Put the things that are true of the whole desk there: the business, the
61
+ standing rules, what the reader is like.
62
+
63
+ The frontmatter is the workspace's defaults:
64
+
65
+ ```yaml
66
+ ---
67
+ timezone: Australia/Sydney
68
+ budget: 60 # a cap in USD for this workspace — per month; or 60/day, 60/week; unset is no limit
69
+ notify:
70
+ email: ops@example.com
71
+ events: [failed, awaiting-approval, completed]
72
+ provider: # see Providers
73
+ base_url: https://openrouter.ai/api/v1
74
+ token: ${OPENROUTER_API_KEY}
75
+ ---
76
+ ```
77
+
78
+ There is an `AGENTS.md` one level up too — the account's — and the two
79
+ compose in a way worth learning once:
80
+
81
+ - **Prose accumulates.** The account's body is added to every workspace's,
82
+ so a rule written at the account cannot be dropped below it.
83
+ - **A frontmatter key replaces whole.** A workspace that sets `notify:`
84
+ replaces the account's `notify:` entirely — it does not merge into it. To
85
+ inherit a key, say nothing about it.
86
+
87
+ The second rule is the one that surprises people: a workspace that declares
88
+ its own `notify:` block silently stops receiving the account's default.
89
+
90
+ ### The clock, all the way down
91
+
92
+ `timezone:` is the one default with levels below the workspace as well as
93
+ above it, because a flow's schedule and an agent's own calendar are both real
94
+ things to set. Nearest wins, and every level inherits the one above it unless
95
+ it says otherwise:
96
+
97
+ ```
98
+ agent frontmatter → flow frontmatter → workspace AGENTS.md →
99
+ account AGENTS.md → FOLDRUN_TIMEZONE → UTC
100
+ ```
101
+
102
+ Whichever level wins sets `TZ`, the date in the agent's prompt, and
103
+ `$FOLDRUN_DATE` in its scripts and its `verify:` shell — so "today" means the
104
+ same thing to every part of a step. Each step's trace names the zone and the
105
+ level it came from.
106
+
107
+ The value is an IANA name (`Australia/Sydney`) or a plain fixed offset —
108
+ `UTC+10`, `GMT-5`, `+10:00`, `-05:30`, or a bare `UTC`. `foldrun check` and a
109
+ deploy both refuse anything else; a bad value that reaches a run falls through
110
+ to the next level with one line in the trace rather than failing the step.
111
+
112
+ ## The account library
113
+
114
+ `<account>/library/` holds tools, skills, knowledge and memory shared by every
115
+ workspace. Resolution is nearest-wins: an agent's own file beats the
116
+ workspace's, which beats the library's. So a shared integration — the tool
117
+ that clones your website, the skill that explains how — is defined once, and
118
+ a workspace that needs a different version shadows it by defining the same
119
+ name locally.
120
+
121
+ From inside a run the library is read-only, reached as `account/…`
122
+ (`account/knowledge/prices.md`). The Library page in the dashboard lists,
123
+ for every shared file, which agents use it and where a nearer copy overrides
124
+ it — that list is the blast radius of changing it.
125
+
126
+ ## Where a run's files go
127
+
128
+ Three directories look alike and are not:
129
+
130
+ | directory | who reads it next | survives a deploy | example |
131
+ |---|---|---|---|
132
+ | `outputs/` | this step, and the archive | no — it is the run's | a draft, a fetched page |
133
+ | `storage/` | a person | yes | the weekly report, a CSV, an image |
134
+ | `state/` | the next run | yes, and a deploy never overwrites it | a cursor, an append-only history |
135
+
136
+ The test is not "is it important", it is **who reads it next**. A value
137
+ regenerated every run is `storage/`; a value accumulated across runs is
138
+ `state/`. From an agent, write `workspace/storage/x.md` and
139
+ `workspace/state/x.md` — the older `../../storage/x.md` is the same place. See [Storage and sharing](storage-and-sharing).
140
+
141
+ ## What a deploy touches
142
+
143
+ A deploy — `foldrun deploy`, or a `git push` to the workspace's remote —
144
+ replaces the source tree: agents, flows, tools, skills, evals, knowledge,
145
+ `AGENTS.md`. It **never** touches `runs/`, `state/`, `secrets.json`, or any
146
+ memory an agent wrote that your push does not mention. Those belong to the
147
+ platform, not to git, and a deploy that reverted what an agent learned would
148
+ make every run a little dumber.
149
+
150
+ A push while a run is in flight is accepted and applied when the run
151
+ finishes; git tells you so at push time. A run parked at an approval gate
152
+ counts as in flight. See [Deploying](deploying).
153
+
154
+ ## Previews
155
+
156
+ Push a branch instead of `main` and the platform deploys a copy of the
157
+ workspace named `<workspace>-preview-<branch>` from that branch's tree, runs
158
+ its evals there, and never fires its schedules. It reads the source
159
+ workspace's secrets. Deleting the branch deletes the preview. It is how a
160
+ change to a live desk gets tried without touching the live desk.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "foldrun",
3
- "version": "0.6.0",
3
+ "version": "0.7.2",
4
4
  "description": "Agents are just folders. Write them, check them, run them — on your machine.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -11,18 +11,22 @@
11
11
  "node": ">=22"
12
12
  },
13
13
  "dependencies": {
14
- "@foldrun/core": "^0.4.0"
14
+ "@foldrun/core": "^0.5.0"
15
15
  },
16
16
  "files": [
17
17
  "bin",
18
18
  "src",
19
- "README.md"
19
+ "README.md",
20
+ "docs"
20
21
  ],
21
22
  "scripts": {
22
23
  "e2e": "FOLDRUN_E2E=1 FOLDRUN_DATA=$(mktemp -d /tmp/foldrun-e2e-XXXXXX) node --test --test-timeout=300000 tests/e2e.test.ts",
23
- "test": "FOLDRUN_DATA=$(mktemp -d /tmp/foldrun-test-XXXXXX) node --test tests/cli-secrets.test.ts tests/cli-check-library.test.ts tests/cli-connect.test.ts tests/cli-accounts.test.ts tests/cli-remote.test.ts tests/cli-stream.test.ts tests/cli-doctor.test.ts",
24
+ "test": "FOLDRUN_DATA=$(mktemp -d /tmp/foldrun-test-XXXXXX) node --test tests/cli-account.test.ts tests/cli-approvals.test.ts tests/cli-stop.test.ts tests/cli-account-settings.test.ts tests/cli-schedule.test.ts tests/cli-billing.test.ts tests/cli-storage.test.ts tests/cli-scaffold.test.ts tests/cli-secrets.test.ts tests/cli-site-login.test.ts tests/cli-check-library.test.ts tests/cli-check-timezone.test.ts tests/cli-check-subagents.test.ts tests/cli-connect.test.ts tests/cli-accounts.test.ts tests/cli-remote.test.ts tests/cli-stream.test.ts tests/cli-doctor.test.ts tests/cli-tool-test.test.ts tests/cli-agent-run.test.ts tests/cli-check-remote.test.ts tests/cli-shares.test.ts tests/cli-triggers.test.ts tests/cli-providers.test.ts tests/cli-rerun-put.test.ts tests/cli-guide.test.ts tests/cli-runtimes.test.ts tests/cli-deploy-safety.test.ts tests/cli-operator.test.ts tests/cli-flow-patterns.test.ts tests/cli-flow-rm-step.test.ts tests/cli-flow-dup-step.test.ts tests/cli-flow-write-stale.test.ts tests/cli-agent-link-stale.test.ts tests/cli-parity.test.ts tests/cli-invoke-inputs.test.ts tests/cli-audit-keys.test.ts tests/cli-version.test.ts tests/cli-check-web-warnings.test.ts tests/cli-report-image.test.ts tests/cli-check-workspace-paths.test.ts tests/cli-parity-dashboard.test.ts tests/cli-api-standards.test.ts tests/cli-backups-onboarding.test.ts tests/cli-check-limits.test.ts tests/cli-gallery.test.ts tests/cli-status-platform.test.ts tests/cli-webhooks-notifications.test.ts",
24
25
  "release": "node scripts/release.mjs",
25
- "typecheck": "tsc -p tsconfig.json"
26
+ "typecheck": "tsc -p tsconfig.json",
27
+ "docs:sync": "node scripts/sync-docs.mjs",
28
+ "prepack": "node scripts/sync-docs.mjs --check",
29
+ "prepare": "(test ! -f .githooks/install.sh || sh .githooks/install.sh)"
26
30
  },
27
31
  "repository": {
28
32
  "type": "git",