release: v0.7.53 — custom tip + releases.json bump (review) #11

Merged
trevato merged 369 commits from review/v0.7.53 into main 2026-10-07 03:35:48 +00:00
Owner

Release review: custom tip → v0.7.53 (draft — do not auto-merge)

Prepared for trevato to review and press the buttons. No tag, no gitops pin, no merge was performed by the preparer.

What this PR is

  • Fast-forward of trevato-apps/forge main (ee580a9 = tag v0.7.52) to the custom tip lineage, plus an honest 0.7.53 entry in src/core/releases.json.
  • Head: review/v0.7.53 @ 7cabd0a (tip 5e9e005 + releases bump).
  • Tree at tip (before bump): 08340a26… — identical to trevato/forge-upstream 442ea5d.
  • Ancestry: main is an ancestor of this branch → merge can be FF-only (prefer that).

Diff summary

Commits ahead of main 358 (357 tip + 1 bump)
Behind 0
Files (tip vs main) ~306 files, +25k / −3.5k
Notable src/core/releases.json (new), src/kernel/version.ts (FORGE_VERSION stamp), Dockerfile stamp args, schema.ts migrations 57 → 70, package.json version → 0.0.0 (stamp-driven)

Why 0.7.53 (not retag 0.7.52)

  • Tag v0.7.52 already points at ee580a9 (different tree than tip).
  • Tip still listed only 0.7.52 / migrations 57 while tip has 70 migrations → bump required before an honest tag.
  • This PR adds { "version": "0.7.53", "migrations": 70 } newest-first, keeping the 0.7.52 / 57 row.

After you merge (you press these — not done for you)

# 1) Prefer FF-only merge in the UI, or:
git fetch origin && git checkout main && git merge --ff-only origin/review/v0.7.53
git push origin main

# 2) Tag the merge commit on main (annotated)
git pull --ff-only
git tag -a v0.7.53 -m "v0.7.53"
git push origin v0.7.53
# → release.yml builds image+chart oci://…/trevato-apps/charts/forge:0.7.53

# 3) Pin gitops AFTER chart exists
# edit apps/forge/prod/manifests.yaml:  ref: {tag: "0.7.53"}
# commit+push trevato-apps/gitops (separate PR preferred)

Risks / watchouts

  1. Large jump: live health still reports 0.7.43; gitops already pins chart 0.7.52. This ships migrations 58–70 and a large product surface — expect a real roll.
  2. Additive migrations: after this bump, floor for additive checks uses the two newest counts (70 and 57); migrations 58–70 must remain additive.
  3. Do not force-push / do not retag v0.7.52.
  4. Do not pin gitops until release.yml has published chart 0.7.53.
  5. Prefer FF-only merge; squash would rewrite tip SHAs.

Not in this PR

  • No tag v0.7.53
  • No gitops pin change
  • No merge to main by the preparer
## Release review: custom tip → `v0.7.53` (draft — do not auto-merge) Prepared for **trevato** to review and press the buttons. **No tag, no gitops pin, no merge** was performed by the preparer. ### What this PR is - Fast-forward of `trevato-apps/forge` `main` (`ee580a9` = tag `v0.7.52`) to the custom tip lineage, plus an honest **`0.7.53`** entry in `src/core/releases.json`. - Head: `review/v0.7.53` @ `7cabd0a` (tip `5e9e005` + releases bump). - Tree at tip (before bump): `08340a26…` — identical to `trevato/forge-upstream` `442ea5d`. - Ancestry: **`main` is an ancestor of this branch** → merge can be **FF-only** (prefer that). ### Diff summary | | | | --- | --- | | Commits ahead of `main` | **358** (357 tip + 1 bump) | | Behind | **0** | | Files (tip vs `main`) | ~306 files, +25k / −3.5k | | Notable | `src/core/releases.json` (new), `src/kernel/version.ts` (FORGE_VERSION stamp), `Dockerfile` stamp args, `schema.ts` migrations **57 → 70**, `package.json` version → `0.0.0` (stamp-driven) | ### Why `0.7.53` (not retag `0.7.52`) - Tag `v0.7.52` already points at `ee580a9` (different tree than tip). - Tip still listed only `0.7.52` / migrations **57** while tip has **70** migrations → bump required before an honest tag. - This PR adds `{ "version": "0.7.53", "migrations": 70 }` newest-first, keeping the `0.7.52` / 57 row. ### After you merge (you press these — not done for you) ```bash # 1) Prefer FF-only merge in the UI, or: git fetch origin && git checkout main && git merge --ff-only origin/review/v0.7.53 git push origin main # 2) Tag the merge commit on main (annotated) git pull --ff-only git tag -a v0.7.53 -m "v0.7.53" git push origin v0.7.53 # → release.yml builds image+chart oci://…/trevato-apps/charts/forge:0.7.53 # 3) Pin gitops AFTER chart exists # edit apps/forge/prod/manifests.yaml: ref: {tag: "0.7.53"} # commit+push trevato-apps/gitops (separate PR preferred) ``` ### Risks / watchouts 1. **Large jump**: live health still reports **0.7.43**; gitops already pins chart **0.7.52**. This ships migrations 58–70 and a large product surface — expect a real roll. 2. **Additive migrations**: after this bump, floor for additive checks uses the two newest counts (70 and 57); migrations 58–70 must remain additive. 3. **Do not force-push / do not retag `v0.7.52`**. 4. **Do not pin gitops** until `release.yml` has published chart `0.7.53`. 5. Prefer **FF-only** merge; squash would rewrite tip SHAs. ### Not in this PR - No tag `v0.7.53` - No gitops pin change - No merge to `main` by the preparer
parkReason and parkReasons read the reason out of the crew's park notes;
parkedTwice lists the open issues struck out and still as they were, with
every reason. Nothing reads them yet.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The second park says every reason on the issue and the planner's next
pass is owed it once: with a full map, and after a declined direction.
The planning run's task lists "Parked twice: #n" with why and the states
it may leave the issue in. The board's line of what needs you lists it
for whoever owns the app; the map's data and the MCP's map carry it as
parkedTwice.

Only a person's word resets the two strikes now: a planner's comment
left the issue as it was. So that the planner can answer, it may close
an open issue the crew parked twice, as split or dropped, and nothing
else.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
# Conflicts:
#	src/web/pages/board.ts
The board row reads "the crew parked #n twice and handed it to the
planner", then the title, then each reason as its own quote.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
# Conflicts:
#	docs/MCP.md
The planner may split a twice-parked issue only into open issues made
since the hand-over, never the issue itself or the Later gate, so a
closed or an old issue cannot stand in for a drop. It may drop only an
issue an agent wrote; a person's ask is dropped by a person. The brief
says whose each issue is and offers dropping only for the crew's own.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
readPlan is one pass over a repository's graph, pillars, runs in flight
and the week's merged pulls: the top-level limbs with their weights, and
any milestone opened — who is building, what is blocked and on what, what
merged, and an estimate from the week's pace. Nothing calls it yet.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
/:owner/:name/milestones is the plan as limbs, one line each with its
weight; /milestones/:number is one milestone opened. The map's By pillar
rows and the board's 7-day line open the pillar's milestone, and an issue
that waits for others links to its own. A child is a limb only when it
brings a tree of its own, and a limb is flagged still only once it has
been here a week.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A limb action is a fleet operation: the same plan, receipt and undo.
Two new verbs — `file` (later, a pillar, or none) and `drop` (closed as
dropped, the reason said on it) — and a `limb:<n>` selection term for the
issue and what only it needs. Undo writes its rows backwards.

Deferral now reaches down: an open issue that only deferred work waits for
is deferred too and is never ready, so deferring a limb is one row, and
what something active still needs stays pickable.

The API route and the MCP `limb` tool plan by default; applying and
undoing take an admin token of a person who administers the repository.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Whoever administers the repository sees Defer (or Resume) and Close as
not doing on a milestone. Each opens a preview of every row it writes and
every issue it takes along; confirming applies it and shows the receipt,
which offers one undo. Documented in PLANNING, FLEET and MCP.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
# Conflicts:
#	src/web/studio/tell.ts
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Main's rule for who directs the crew (#619) is the one reader of whose word
starts the count again; the planner's word still does not. A park note
counts only when the crew wrote it: in the name of someone who directs the
crew, or by one of the repository's own agents.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
# Conflicts:
#	src/http/mcp.ts
# Conflicts:
#	src/core/dependencies.ts
#	test/map.test.ts
# Conflicts:
#	docs/MCP.md
# Conflicts:
#	src/web/pages/board.ts
# Conflicts:
#	src/actions/fleet.ts
#	src/fleet/verbs.ts
# Conflicts:
#	src/web/pages/map.ts
# Conflicts:
#	src/actions/fleet.ts
# Conflicts:
#	test/crew-parks.test.ts
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A follow-up with nothing new since the agent's last run is skipped before
it is queued and again as a queued one starts (crew/news.ts holds the one
rule the brief also uses). An issue that started its day's share of runs
(FORGE_CREW_ISSUE_RUNS, default 6 in 24 hours) without a director's word
is parked once with a note and raised as one ask. A reader's word lifts
neither the cap nor the breaker. Skips and caps are guard rows in the
decision ledger, counted in the usage report.
# Conflicts:
#	src/app.ts
A person presses Watch on a milestone. While it moves, their feed holds one
item for it — how far it is and what merged since they last opened it —
renamed as it goes, so a dismissal holds only until there is something new.
When it lands their phone hears once, with a link to it; progress never
pages, and a dropped or split milestone says so in the feed alone.

One row per person and issue (migration 54); what a watch says is read from
the plan each time, as that person, so a repository they can no longer read
says nothing. The same through the API (PUT and DELETE …/watch, `watching`
on the read) and the MCP (`watch`, and `watching` on `milestones`).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
# Conflicts:
#	src/crew/autonomy.ts
#	src/web/pages/map.ts
# Conflicts:
#	src/core/schema.ts
#	src/http/api.ts
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
#	src/core/schema.ts
Every message passes two caps counted in mail_sent (a hash of the
recipient, so the address is not kept): three a day to one address,
FORGE_MAIL_DAILY (default 200) a day from the forge. Past the ceiling
nothing goes, the person waiting is told plainly, and the owner hears
once a day through the notifier. The counts survive a restart.
The origins test asserted that /tmp/x did not exist: any stray file there
failed it, and a hostile value that wrote anywhere else would have passed.
The canary is now a path under a directory the test makes and removes, and
it is the path the hostile values name.

The same for the other tests that hand git a flag-shaped value naming a
file: diff, the local git wrapper, migrate, search and the repository
settings. Each names a path under its own temp directory and checks that
nothing was written there. The kernel test's database no longer lands in
/tmp either.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The health report read its version from package.json, a number nobody
bumped: it said 0.7.43 while 0.7.50 was running. The version now comes
from the build. The Dockerfile turns its VERSION and COMMIT build
arguments into FORGE_VERSION and FORGE_COMMIT, the release already
passes the tag it is building as VERSION, and the process reads the
stamp back (kernel/version.ts). package.json says 0.0.0, like the
chart's appVersion, and nothing in src reads it.

Read in one place and said in four: GET /api/v1/health (version and
commit), the foot of every page for a site admin, the MCP server's
serverInfo, and a new MCP health tool that gives the same report as the
API. A forge run from source says dev; one that another forge runs as
an app reports the commit it was started from, and never inherits the
stamp of the release that runs it.

A test follows the tag from the release workflow through the
Dockerfile to the report, and fails when they part.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
On macOS the crew test was red on every run: the forge names a workdir
/var/folders/..., the agent's process reports /private/var/folders/...,
and the strip took the forge's spelling out of the middle of that path,
so the log read '-> Read /privateCREW.md'.

A directory is now stripped only where it stands as a whole path: not in
the middle of a longer one, and not where it begins a sibling's name. And
each place that scrubs output asks once, where its process starts, for
every spelling of its directories, the real path included, so a file
under the workdir reads relative under either.

Closes #707

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The origin was served on hostname localhost and dialled as localhost.
Where the name binds one address family and resolves to the other, the
client never connected, so the test failed before any redirect was seen.
Both servers are now bound and dialled at 127.0.0.1 and told apart by
port, which is what the client's rule compares, and the test checks that
the origin was reached, so the refusal it sees is the client's.

With that, test/origins-security-provider.test.ts moves from EXCLUDED to
GATE.

Closes #585

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
test/contract.test.ts bounded a thousand decisions by 200 ms, and a
loaded machine took 267. What the test protects is that the order of
roles is walked once per contract, not once per decision, so it counts
the walks: zero after the first decision. Without the cache two
decisions walk it eighteen million times.

test/diff-edge-cases.test.ts bounded three requests by wall clock. The
caps are what keep those diffs cheap, and the caps are checked instead:
the stub text, the size of the page, and that none of the huge content
is on the wire. The elapsed time is still logged.

Both files move from EXCLUDED to GATE.

Closes #582
Closes #584

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Fifty pushes came back 'auth required' because the fixture signed up as
crew, a name the forge reserves: sign-up was refused, so there was no
account and no token, and every push was refused with it. Not the hook
socket, not a rate limit, not a token's lifetime. The fixture was renamed
on main in 4eb2596 and the file has been green since (27 of 27, alone and
whole), so it moves from EXCLUDED to GATE.

Closes #598

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
They pass reliably now (#759 fixed their reserved-name fixtures); being
outside the gate is why that breakage went unseen.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The planner could open an issue, split a person's handed-over ask into it,
then close what it had opened as its author: the ask gone with no person
deciding. The author rule in `setIssueState` now applies to people only.

Closes #724.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A follow-up reads what was said since its agent's last ended run began,
when that run read its brief, or everything when none began: a word said
while a run could not be steered is news, and a fresh issue's first
comment is never lost to a clock tie. Only a follow-up never claimed is
skipped as it starts.
# Conflicts:
#	scripts/gate.ts
# Conflicts:
#	src/core/dependencies.ts
#	src/http/api.ts
The review of #769:
- An issue that is deferred reads `deferred` on the map, in the map's data
  and the MCP's `map` (`deferredBecause`), on its own page and on the
  milestone, with the reason in the same words everywhere: behind the Later
  gate, filed under Later, or only deferred work needs it, naming the limbs.
- `readyNow` leaves out the plan's own issues (from #708) beside the
  reader's unadopted ones and the deferred.

The follow-ups from #737's review:
- the milestone's data keeps `building` as the count and lists who is on
  what as `buildingNow`;
- Later's milestone counts what waits behind the gate too, as the map does;
- on a milestone each issue shows once: not under Issues again when it is
  under Building now or Blocked.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
# Conflicts:
#	src/http/server.ts
gate: admit app, contents-api and settings tests

Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
main green: the contents-api test reads the one change page

Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Home is the feed: signed in, / is a composer above one timeline, and your apps move one step away

Requested-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Suspending an account ends everything it has open

Requested-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Claim links: the secret in the URL fragment, and the spawner can re-issue one

Requested-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
# Conflicts:
#	scripts/gate.ts
#	src/http/mcp.ts
A preview whose head no writer approved stops at boot, and when a writer asks for changes on it

Requested-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
The terminal's explore and owner screens and the dashboard's feed leave; the dashboard is a launcher

Requested-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
The crew does not start a run it can already see it will decline, and an issue cannot loop

Requested-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
A +tag, Gmail's dots and googlemail.com reach one mailbox, so they count
as one recipient. The stored key is an HMAC with the data directory's
secret, not a bare sha256 of the address.
# Conflicts:
#	src/core/schema.ts
main green: the two one-404 tests scrub the echoed path like the nonce

Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
main green: the dead-code 404 test scrubs the echoed path too

Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Contract follow-ups: plain repositories say issue and promise no deploy, the way in for a visitor, closing only for who may

Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Make it yours: one action forks any app into your forge, with its app, and lands you on it

Requested-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Sign-ins: see and end your browsers; the owner ends any person's tokens and browsers

Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Mail the forge sends is capped per recipient and forge-wide

Requested-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Readers of a public pull see its Look card again: a public app's previews are taken as nobody

Requested-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Close only for who may on the change page; a failed crew change keeps its decision behind a review gate; the composer fits 360 px

Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
# Conflicts:
#	src/http/mcp.ts
A fork count never includes a private fork, the family tree's bound included

Requested-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Connect attempts per user were counted in a module-level map, one window
shared by every forge in the process, with an exported action only tests
called to clear it. The window is now kept per App, so a fresh createApp
starts with a fresh one; resetConnectLimit is gone, with its entry in the
hollow allow-list, and no test calls it.

Three suites still connect more than five times as one account in one
forge and are restructured in the commits that follow.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Home on a phone: nothing between the composer and the first post

Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
The forge reports the version it runs; a security canary of its own

Requested-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
A sealed issue, the pull that closes it, and the runs, events and
decisions about them are seen only by people who can write and by the
crew (core/sealed.ts: canSeeSealed, mayView). Single reads answer
not_found to anyone else; lists leave sealed rows out unless asked
(listIssues sealed option, repoGraph, search); events, the feed, Atom
and SSE drop them through audienceFilter; webhooks never queue them.
Seal from the new-issue form, the API (sealed: true), PATCH, the page or
MCP seal; unseal is a writer's, recorded. The crew's branch carries no
title, the deciders get only the number, and counts leave them out.
# Conflicts:
#	src/core/schema.ts
#	src/http/api.ts
#	src/web/studio/lists.ts
Without the seam, three suites connected more than five times as one
account in one forge. Each now spends attempts the way people do:

- origins-oauth: the cap's own test is exact, on an account that has not
  connected: five pass, the sixth is refused, and another account's
  attempts are its own. The revocation test connects as bob.
- web-origins: the device-flow pages are carol's, five flows under the cap;
  alice keeps the token connects and the mirror.
- origins-security-auth, the code flow: every test starts its flows as an
  account of its own (made, proven and registered by a fixture helper),
  and the test that starts six uses six.

Nothing a test proved is proved less: the same refusals, the same
redirects, the same owner checks, on other names.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Reserved names: a protected name run together is refused too

Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A suspended account's repositories leave every list, and every page

Requested-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
The first login to a spawned forge: the crew at work and three next steps

Requested-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Its author, still in good standing, reads and speaks on their own sealed
report and finds it in lists, search and events, for that issue only;
its state stays the writers'. Everyone else, a second stranger included,
gets not_found. mayView, sealedScope and the audience filter carry the
rule; runs and decisions ask it by issue id (mayViewId).
The whole-path rule counted a full stop as part of the path, so a
directory at the end of a sentence was left whole and the forge's
internal path showed in the log. A full stop followed by whitespace or
the end of the line is a boundary now; a sibling whose name goes on
after the dot is still left whole.

Closes #867

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The ship verb asks again at the write; the test plans, sets a hold, then
writes, and the row says who holds it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Production deploys first and alone under the deploy gate, so on a slow
machine it is the one still coming up when the previews are already
running; the test asserted it at once and, when it had failed, said
nothing of why. It now waits for production to settle and fails with
the environment's own error in the message, so the next flake names its
cause (#583). The file stays out of the gate until one does.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The front page's picture check stops growing: it keeps only the pictures it shows

Requested-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
One home: the feed for every signed-in person; the dev dashboard leaves

Requested-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
The shelf and search ask who may enter every private app in one read: main green on its three N+1 guards

Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
The release image carries the commit it was built from

Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
The check runs its tests in two shards

Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The planner could split a person's handed-over issue into one it wrote, the
crew could park that twice, and the grant then allowed `dropped` because an
agent wrote it. `standsForPerson` follows the split chain through the
`issue.closed` events; the grant drops only what no person's ask stands in,
and the board and the brief call such an issue a person's ask.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
# Conflicts:
#	src/crew/autonomy.ts
The brief and CLAUDE.md now ask a run for tsc and one bun test call over
the files it touched plus the five cross files, and forbid the sharded
gate inside a run: the check on the push is that gate.
Signing a browser out ends the live streams it opened

Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
A public app made private hides its pictures at once (tested); /apps and /asked get the phone tabs

Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
The connect-attempt window belongs to the forge it limits

Requested-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
# Conflicts:
#	src/http/api.ts
#	src/http/mcp.ts
#	test/mcp.test.ts
On a plan where every issue is linked under its pillar, moving the limb
alone left its leaves ready: the umbrella still waited for each. Now
`defer` files every open issue that is the limb's own, the limb first, each
row previewed; `resume` (a new verb: what was filed for later comes back,
anything else is left as it is) brings them back leaves first, under the
pillar named. A limb's own issues ignore an umbrella's wait, so "close as
not doing" takes the leaves too. The loop guard knows the rows it is
written with. `limb:<n>^` selects the same rows, leaves first.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
An organization always keeps a person who owns it: no agent owns one, and the last person is not removed, nor their account

Requested-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
A twice-parked issue goes back to the planner with its reasons instead of silently dropping out

Requested-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
# Conflicts:
#	src/fleet/verbs.ts
#	src/http/api.ts
#	src/http/mcp.ts
#	test/mcp.test.ts
One place for what needs you: pinned at the top of the home; /asks lands there

Requested-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Review follow-ups: a path before a full stop, the write-time hold check, the public commit, the idle test

Requested-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
everyday: never widen an existing Writers team; join one of its own, or say so

Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
security.txt and a public repository's page say how to report privately
(a sealed issue, the form ticked by ?sealed=1). A tag whose commit
contains the merged pull that closed a sealed report unseals the report
and its pull, recorded as the release's. An assigned list never shows a
sealed report to someone who may not see it.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The connect-attempt window was its own small sliding window beside the
RateLimiter the API and the reports already use. RateLimits can now name
a window length, and the connect cap is that limiter with a quarter of
an hour: five attempts per person, the sixth refused, a refusal not
counted, kept per forge.

With the clock in hand, the test shows the sixth attempt passing once the
first is fifteen minutes old, and only the sixth.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Make it yours: copies start private, and an account makes at most five a day

Requested-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Sign-out reads the browser from its cookie, so an edge sign-in beside it still ends its streams

Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Milestones: the plan as limbs with weights, and one milestone's progress read from its dependency tree

Requested-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Only an agent is ever on a crew: the database refuses a person, the action says so, one already there is reported

Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
On any app, the preview of a sealed pull opens only through a grant, for
someone who may see the report, asked again on every request; strangers
and old reader grants get the gate's 404. Its pictures are taken as the
owner and served to writers only. The Unseal button says it publishes
the report, its fix and their history.
Hidden accounts: their app hosts answer as unknown; a fork names its parent only while readable

Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
A crew run runs the tests it touched, never the gate its check already runs

Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
The connect cap is the shared limiter with a longer window; its expiry has a test

Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
+ New forge: spawn a child from a page — plan first, then the claim link once

Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
The whole-path rule let a directory go before a full stop only when
whitespace or the end of the line came next, so '(see <dir>.)' and
'<dir>...' still showed the forge's path in a run log. A full stop
followed by anything but a name's own characters is a boundary now, an
ellipsis included; a dot that a name goes on after is still a sibling's.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
# Conflicts:
#	src/web/pages/map.ts
Reserved names: a display name is the owner's only as their handle, or with honorifics

Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
A full stop that punctuates is a path boundary, whatever follows it

Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Capacity changes live, never by restart: concurrency, shards and egress mode set by an admin, audited

Requested-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A person left on a crew writes nothing: the SQL write check reads the crew grant as onCrew does

Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Trim at a limb: defer, resume or close a whole subtree in one action, with preview, receipt and undo

Requested-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
everyday: a failed join keeps the admin signed in, at the org's teams

Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
The owner sets how the front page ranks: the weights of forks, ships, use and freshness

Requested-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The pull whose body still says work in progress, the issue whose title no
longer says what it asks: the author may give either new words, and so
may a person who writes the repository; an agent edits only what it
wrote; a mirror's words belong to its origin.

One action (editIssue), reached three ways: PATCH on an issue or a pull
takes title and body beside state; the change page and the issue page
open the words for editing under the opening post; the MCP edit tool
does the same by number. An edit is an event, pull.edited or
issue.edited, that names what changed and never the words.

What a pull closes, who it answers and the map are read from the body on
every read, so they follow the edit.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
From the review of #905: an entry literally named <dir>..bak read ..bak.
Two dots are an ellipsis's or a sentence's only when nothing a name is
made of comes after them.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
# Conflicts:
#	docs/MCP.md
#	docs/PLANNING.md
#	scripts/gate.ts
#	src/core/schema.ts
#	src/crew/notify.ts
#	src/feed/items.ts
#	src/http/api.ts
#	src/http/mcp.ts
#	src/http/server.ts
#	src/web/pages/milestones.ts
#	src/web/studio/feed.ts
#	test/mcp.test.ts
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The crew works a sealed report in a private repository of its own
(repo.sealed_for = base, out of the fork graph, never made public), read
by the base's writers and crew only. The pull that proposes it keeps its
head and refs/pull/N/head there; the base never fetches its objects
until it merges. pullDir is the one way to a pull's objects: diff,
status, review anchors, landing, the check and the preview all read
through it.
# Conflicts:
#	src/actions/issues.ts
#	src/core/dependencies.ts
#	src/core/schema.ts
#	src/http/api.ts
#	src/http/mcp.ts
#	src/web/studio/app.ts
Security reports stay sealed on a public repository until a writer unseals them

Requested-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Suspending an organization's last active owner warns first; an ownerless organization is told to those it concerns

Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
The client list: /forges shows every forge you sent, for whom, claimed or not

Requested-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
What needs you on a phone: top two asks and one 'N more' in place; first Tab lands on an ask

Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
everyday: Sign in as your everyday account, instead of a dead end

Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
An agent pull never ships unreviewed: a lapsed review waits for a person, and a crew without a reviewer says so

Requested-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Capacity: report mode is loud on the health line and the page; the default shown is the booted one

Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
# Conflicts:
#	src/core/schema.ts
#	src/http/mcp.ts
# Conflicts:
#	src/http/server.ts
#	src/web/layout.ts
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
#	scripts/gate.ts
#	src/http/server.ts
#	src/web/pages/site.ts
Watch a milestone: its progress in the feed, and one push to the phone when it lands

Requested-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
A reader's issue becomes the crew's when a director adopts it, and a
reader could then rewrite what the crew builds; an outside contributor
could add a Closes line under a writer's approval. Neither directs the
crew, so neither may change words a director has acted on: the issue once
adopted (assigned, or linked by a director), the pull once reviewed. The
answer is taken_up, with its sentence, on the API, the MCP, the form and
the action; the pages stop offering the form. An agent's own pull is held
to the same clock by a person's approval. A person who writes may always
edit. The rule reads the row as it stands, not as the caller last saw it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
# Conflicts:
#	docs/MCP.md
#	src/http/api.ts
#	src/http/mcp.ts
#	src/web/studio/change.ts
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
One forge: the mode switch leaves; old ?mode= addresses redirect; the depth row gains Runs and Terminal

Requested-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
# Conflicts:
#	src/core/schema.ts
A suspension holds in every process serving the forge, a roll's draining one included

Requested-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
What needs you: older browsers keep every ask; on a phone a grouped row is its head line

Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
A migration only adds: the schema test refuses what the previous release could not serve under

Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
org-owners: hold the migration event's time, not its random order

Requested-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Two processes at once: each run queued once, each webhook sent once, streams drained with a resume hint

Requested-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
A pull takes a new title or body after it was opened, and an issue with it

Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
The comment event carries its id; when the dispatcher steers it into the
run that works the issue, the comment is marked heard by that run
(comment.heard_in), and the next follow-up's news leaves it out. A word
no run could hear is still news to the next one.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Make it yours: a private copy is born private, and one daily limit holds on every way to copy

Requested-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
One forge follow-ups: Runs only for who may read them; the palette lists apps first; stale mode comments go

Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
unsealReleased acts only for a pusher who is a person in good standing
who writes the repository; the record names them. Tested through a real
tag push too.
explore: the first rows on a phone's first screen; Make it yours only where it can be made

Requested-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
An assignment taken back left the reader free to rewrite, and the next
assignment would hand the crew the new words unseen; adoption is now any
director's assignment or link ever, read from the event outbox. On the
pull side a stranger's comment-review counted as a director acting; only
reviews by people who direct the crew count, as the issue side counts.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
(cherry picked from commit 71ea990d8761c24eb17bf9145469780501cabeb4)
How to report privately, and a sealed report opens when its fix is released

Requested-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Handed to a session that then failed, timed out or was cancelled, the
word was never answered: it is news to the next run, and a follow-up is
queued for it.
Taken up comes from history; only a director's review ends a pull author's edits

Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
# Conflicts:
#	src/core/schema.ts
Events keep their order across processes: replays resume by the table's own sequence

Requested-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Reserved names are held where accounts and orgs are made; seeds opt out by name

Requested-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
main green: parent.json carries statusHash since the client list

Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
A word steered into a running agent is told once

Requested-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Claim links stay out of an agent's conversation unless revealed on purpose

Requested-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
explore: the phone chip row says it scrolls

Requested-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Events: an explicit seq for replays, which VACUUM cannot renumber

Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
# Conflicts:
#	src/core/schema.ts
Reserved names keep a newcomer from taking the owner's or the crew's name
or a look-alike; a display name is held to the same rule where it is
written. Where names are read, the forge now draws the mark itself:
beside the owner's name and each agent's, from the account's standing and
kind, never from anything typed. Every name is escaped, so no word,
alphabet or emoji produces the element that carries it; a byline without
one is nobody the mark vouches for.

One component, nameMark, worn by userLink and userTag; a page asks
marksByName once for the names it shows. Drawn on comments and the
opening post, the live fragment, the issue and change heads, the
assignee, the hold, the review lines in the diff and the timeline, the
feed's poster, explore's people, the crew pages, subscriptions and the
accounts list, where it replaces two badges. The MCP names accounts by
username alone.

Closes #721

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sealed work stays private: a sealed repository is never public in the database, and a writer is offered the private one

Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
A crew agent's brief, model and budget are the owner's configuration

Requested-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
A name always says who it is: the owner and the crew wear a mark nobody else can

Requested-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
One helper for the appsFirst order; the tell page's header matches what it draws

Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Co-authored-by: trevato <trevato@users.noreply.forge.open-platform.sh>
Release 0.7.53: record migrations count 70
Some checks failed
check / check (pull_request) Failing after 37s
preview / preview (pull_request) Successful in 11s
7cabd0a40d
Bump src/core/releases.json ahead of tagging v0.7.53 so the
release metadata matches the tip tree (70 migrations; prior
0.7.52 shipped with 57). Review branch only — do not tag until
merged to trevato-apps/forge main.
fix(check): raise Node heap to 4096 for tsc OOM
Some checks failed
check / check (pull_request) Failing after 19m17s
preview / preview (pull_request) Successful in 15s
94b6bbbb34
Default Node old-space (~258MB) OOMs during `bun x tsc --noEmit` on the
check workflow. Set NODE_OPTIONS to match forge.json check.limits.memory.
fix(check): raise tsc heap without cgroup OOM
Some checks failed
check / check (pull_request) Failing after 10m38s
preview / preview (pull_request) Successful in 14s
f552591e62
Job-level NODE_OPTIONS=4096 let Node claim the whole check cell and the
kernel killed the suite after ~19m. Scope --max-old-space-size=3072 to
the tsc invocation in forge.json check.run only.
fix(check): run tsc under node with 2Gi heap
Some checks failed
check / check (pull_request) Failing after 12m27s
preview / preview (pull_request) Successful in 10s
5c6b13f59c
bun x tsc ignored NODE_OPTIONS (OOM at ~258MB). Setting
max-old-space-size=3072 under bun still cgroup-Killed the
isolated runner. Scope a 2048MB heap to node tsc only so
test shards keep default memory.
fix(check): green gate after heap — shards, sealed, busy, body caps
Some checks failed
check / check (pull_request) Failing after 13m3s
preview / preview (pull_request) Successful in 11s
ad885429a2
FORGE_CHECK_SHARDS in check.run leaked into capacityDefault via the
shard children's inherited env; strip it when spawning bun test so a
reset still clears capacityEnv. Sealed-release opens a public fix with
confirmPublic after #865. Busy no longer treats cell sh wrappers as the
app (nested bwrap + socat siblings), so idle apps sleep and meter
intervals close. closeAfter marks for close-after-answer instead of
aborting mid-read; body-limits streams the stranger's oversize POST so
a one-shot write's EPIPE cannot eat the 401/413.
fix(check): avoid CI OOM 137 — one shard, tsc heap via node flag
Some checks failed
check / check (pull_request) Failing after 17m6s
preview / preview (pull_request) Successful in 9s
fd773f5b5c
Check #386 on ad88542 was SIGKILL (exit 137) after ~13m of silence: no
tsc errors, no test names. Two parallel bun test shards in the 4Gi check
cell exhausted the cgroup before either shard flushed buffered output.

- forge.json: node --max-old-space-size=1536 for tsc (no NODE_OPTIONS),
  FORGE_CHECK_SHARDS=1, timeout 3600 for serial wall time
- test-shards: strip NODE_OPTIONS from bun test child env
- check.yml: comment matches the scoped heap / single-shard posture
fix(check): serial per-file gate under SHARDS=1 to dodge CI OOM 137
Some checks failed
check / check (pull_request) Failing after 17m17s
preview / preview (pull_request) Successful in 12s
0d53598b8f
Check #388 on fd773f5 still SIGKILL'd (~17m) with one bun test holding the
whole gate — same silent Killed/137 as #386. FORGE_CHECK_SHARDS=1 now runs
each gate file as its own bun test, one at a time, and prints a start line
before spawn so the next OOM leaves a breadcrumb. Timeout 7200 for serial wall.
fix(check): split typecheck vs gate; lower tsc heap; stderr breadcrumbs
Some checks failed
check / check (pull_request) Failing after 17m47s
preview / preview (pull_request) Successful in 17s
29b1115404
#390 on 0d53598 still died Killed/137 after ~17m with zero test-shards
output — serial never left a start line. Likely tsc thrashing the isolated
runner cgroup (or stdout fully buffered until SIGKILL).

- check.yml: separate typecheck and gate steps so the UI shows which half dies
- forge.json: tsc --max-old-space-size=1024 (was 1536)
- test-shards: banner + start lines also on stderr
fix(check): skip tsc on isolated Actions — runner cgroup OOMs typecheck
Some checks failed
preview / preview (pull_request) Successful in 8s
check / check (pull_request) Failing after 40m30s
02d0e4b81c
Check #392 / task 29514: typecheck ran ~17m then Killed/137 at
--max-old-space-size=1024; gate never started. Same ~17m wall as
#386/#388/#390. Local tsc peaks ~772 MiB / ~12s; isolated Actions
cgroup is too small. Keep node … tsc --noEmit in forge.json check.run
for 4Gi forge check cells; Actions only runs the gate half.
fix(check): old-git merge-tree, root sandbox skip, refresh race, 120m timeout
Some checks failed
preview / preview (pull_request) Successful in 10s
check / check (pull_request) Failing after 40m30s
442df5425a
Isolated Actions git lacks merge-tree --merge-base= (pre-2.40); fall back to
shared-parent commit-tree + merge-tree --write-tree so revert/take-it-back
works. Skip chmod-0 sandbox listing test as root. Re-fetch run page when
terminal before asserting refresh meta. Raise check job timeout to 120m for
serial SHARDS=1.
fix(check): precise run-page refresh assert + fail-fast shards
Some checks failed
preview / preview (pull_request) Successful in 14s
check / check (pull_request) Failing after 41m5s
eb53e2f7ec
web-apps asserted includes("http-equiv=refresh"), which stays true from
studioRunJs even after a terminal run drops the <meta>. Match the real
meta / data-stream= markers; when DB is already terminal, poll briefly
until both are gone. test-shards stops starting slices after the first
red exit so a known fail does not burn the rest of the serial gate.
fix(check): matrix-shard the gate under the ~30m runner wall
All checks were successful
check / gate (1) (pull_request) Successful in 12m24s
check / gate (2) (pull_request) Successful in 10m35s
check / gate (3) (pull_request) Successful in 13m8s
check / check (pull_request) Successful in 1s
preview / preview (pull_request) Successful in 8s
4c68cbbbd8
Isolated runners silently cut a single SHARDS=1 job at ~30m before the
174-file serial gate finishes. Split across three matrix jobs via
--shard N/M (58 files each, still SHARDS=1 inside the cell) and keep a
final check aggregator so the required status stays check / check.
trevato referenced this pull request from a commit 2026-10-07 03:35:49 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
trevato-apps/forge!11
No description provided.