Commit Graph

102 Commits

Author SHA1 Message Date
emdashbot[bot] 4c3edadeec ci: release (#2419)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-08-18 13:26:49 +01:00
Matt Kane f1ab3f93aa fix(bot): make verification efficient and recoverable (#2537)
* fix(bot): focus implementation verification

* fix(bot): keep verification commands stable

* fix(bot): prevent verification history wedges
2026-08-18 12:22:47 +01:00
Matt Kane a07b4a5379 fix(bot): summarize and resume timed-out runs (#2536)
* fix(bot): preserve timed-out runs for resume

* fix(bot): recover rejected resume dispatches

* fix(bot): dedupe resumed deliveries atomically

* fix(bot): confirm resumed agent callbacks
2026-08-18 08:57:28 +01:00
Matt Kane a8b9483fd2 fix(bot): preserve context for long write runs (#2532) 2026-08-17 17:39:05 +00:00
Matt Kane a927afe2af docs: add EmDash documentation writing skill (#2529)
* docs: add EmDash documentation writing skill

* style: format

* ci: review documentation with writing skill

* docs(agents): load documentation writing skill

---------

Co-authored-by: emdashbot[bot] <emdashbot[bot]@users.noreply.github.com>
2026-08-17 14:47:25 +01:00
Matt Kane 68a8593b5a fix(bot): preserve workspaces through sandbox restarts (#2530) 2026-08-17 13:01:06 +00:00
Matt Kane 87d201ffa5 fix(bot): classify comments with one AI call (#2528) 2026-08-17 12:12:15 +00:00
Matt Kane f4a33e6394 chore: commit generated worker types in flue-review and playground (#2392)
* chore: commit generated worker types in flue-review and playground

* fix(playground): include generated worker types
2026-08-12 16:57:21 +01:00
Matt Kane 4a6cd0bfa8 fix(bot): harden automated candidate delivery (#2429)
* fix(bot): harden automated candidate delivery

* fix(bot): address candidate delivery review

* fix(bot): keep implementations retryable
2026-08-12 09:07:42 +00:00
emdashbot[bot] a891d73232 ci: release (#2350)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-08-11 15:49:52 +01:00
Matt Kane 2a7ab0e634 fix(bot): bake Chrome into the sandbox image at build time (#2416)
The sandbox egress allowlist only passes GitHub/npm hosts, so agent-browser's
runtime Chrome download can never succeed inside a container; the browser has
to ship in the image. Install it in the node-source stage (working CA bundle,
same pattern as the Node copy) and copy the cache across. Verified with
agent-browser doctor's live launch test plus an open/get-text round-trip in
the built image.
2026-08-11 07:31:15 +01:00
Matt Kane d6e3197a76 chore(emdash-bot): eval harness + gen-1 cutover (bot next-gen 5/5) — merge gated on evals (#2383)
* feat(emdash-bot): investigation eval harness + pre-fix ref checkout

Operator tool (pnpm evals) that drives the deployed worker's investigate
agent against 26 curated closed issues and scores each verdict against
recorded ground truth. Gate: zero confident-wrong (a reproduction asserted
on a case with nothing to reproduce). Cannot run in CI; the dataset loader,
pre-fix SHA resolution, scorer, and formatter are unit-tested.

Adds an optional baseRef to the investigate agent so a run can stand up at a
fixing PR's pre-fix commit; cloneRepo and the container checkout now resolve a
branch, tag, or bare commit SHA uniformly.

* chore(emdash-bot): cut over to the worker; retire gen-1 Actions bot

Delete the gen-1 .flue/ workspace and four issue-automation workflows
(investigate, reporter-reply, maintainer-reply, bot-cleanup) now that the
emdash-bot worker owns issue-side automation. The repro/diagnose/verify skill
prompts were already ported into the worker. Clean the dead investigate.yml
entry from zizmor.yml and a stale reference in a preview-releases.yml comment
(comment only; the workflow is independent and untouched).

Keep triage-project-sync.yml: board sync needs org-level Projects v2 write and
keys off the retired triage/* labels, so it is a later singleton, not a cutover
change -- documented in evals/CUTOVER.md. Rewrite TRIAGE.md's bot sections for
the maintainer-directive flow, the reporter preview-confirm loop, and the new
bot:* state labels. evals/CUTOVER.md drafts the cutover PR body and holds the
eval-gate section to fill after the live pre-flight run.

* chore(emdash-bot): drop dead labelTriggers; correct drift-reconcile comment

Nothing reads EventMeta.labelTriggers and the webhook skips labeled/unlabeled
events, so no bot:* label fires any event -- comments are the only entry. Remove
the labelTriggers from all four events (repro/investigate/implement/fix) and the
now-orphaned field, and regenerate machine.json. Correct the normalizeIssues
comment: label drift is reconciled by the Orchestrator DO's periodic alarm tick
(reconcileLabels), not a cron -- the worker has no cron trigger.

* style: format

* fix(emdash-bot): quote dynamic values in container setup commands

* chore(emdash-bot): drop stale workflow references from machine.ts comments

* docs(emdash-bot): match TRIAGE.md to the mention-only trigger; drop deleted-workflow references

* fix(emdash-bot): drop the experimental compatibility flag; deployed workers reject it and the worker loader runs without it

* fix(emdash-bot): export WorkspaceServiceProxy so the worker-shell loopback resolves

* fix(emdash-bot): install @platformatic/vfs for computer's in-VFS git

* fix(emdash-bot): hydrate the VFS from the GitHub tarball; in-VFS git clone exceeds DO memory

* feat(emdash-bot): move the isolate VFS to @cloudflare/shell with a durable change log

Replaces @cloudflare/computer, whose SQLite provider cannot serve a
repo-sized tree in a deployed DO. The agent's own DO hosts a
@cloudflare/shell Workspace (R2 spill); container materialization replays
a durable write log instead of parsing git status; the code tool is a
read-only analysis surface; git and the toolchain live in the container.

* fix(emdash-bot): degrade gracefully when no usable App credential exists

* fix(emdash-bot): cap tool results and harden reporting discipline

Unbounded tool output burst kimi's context window on long
investigations (five eval errors); every tool result now truncates at
24KB with a narrowing hint, and the code tool describes its read-only
surface compactly instead of embedding the full state typings.
report_result and the investigate skill now require a demonstrated
failure for reproduced=true and route missing-information cases to
verdict=unclear (needs_info).

* fix(emdash-bot): give read_file a line range, raise the result cap, and demand the demonstration attempt

* fix(emdash-bot): reproduced means the reported issue; adjacent findings and infra symptoms report as findings

* fix(emdash-bot): move reproduction discipline into the result schema

The report schema now carries demonstration (how the failure was shown)
and demonstratedReportedIssue (whether it is the reporter's defect), and
rejects reproduced=true without both -- the distinction prose tuning
kept missing in both directions. A faithful-path demonstration counts:
a failing unit test reproduces a UI-reported defect.

* feat(emdash-bot): first-class diagnosed verdict for root causes without a confirming repro

rootCauseFound on the agent result maps to a new agent.diagnosed event
and bot:diagnosed state, actionable like reproduced (the fix loop still
verifies with a failing test first). The eval scorer grades it
separately from pass and miss; a diagnosed claim on a negative case is
a miss, not confident-wrong.

* style: format

* chore: sync lockfile with emdash-bot dependency swap

* docs: record run-7 eval gate result in CUTOVER.md

* style: format

* feat(evals): relabel #1193 as an unfixed confirmed bug; sharpen skill verdict discipline

The agent's run-7 reproduction of #1193 (update() overwrites published_at)
was independently confirmed; the NOT_REPRODUCIBLE label was wrong. Unfixed
confirmed bugs (fixing_pr: null) now run at main with no pre_fix.

Skill: needs-info reports settle before standing up the toolchain (run-7
#1113 burned its 30-minute budget building against an underspecified
report), and rootCauseFound requires a located code defect, not an
explanation (negatives were landing diagnosed instead of not_reproduced).

* docs: record run-8 eval gate result

* feat(evals): relabel #1022 as an unfixed confirmed bug; gate passes

Maintainer adjudication: the agent's asserted reproduction (legacy seo data
rejected as an unknown field by validateContentData) is a real, unfixed bug;
the NOT_REPRODUCIBLE label was wrong. Run 8's stored verdicts re-scored
against the corrected dataset read GATE PASSED (16 pass, 1 diagnosed, 9 miss,
0 confident-wrong, 0 errors); CUTOVER.md records the result.

---------

Co-authored-by: emdashbot[bot] <emdashbot[bot]@users.noreply.github.com>
2026-08-10 20:11:56 +01:00
Matt Kane f6385dab2c refactor(cli): deprecate emdash dev (#2405)
* refactor(cli): remove dev command

* refactor(cli): deprecate dev command
2026-08-10 13:41:21 +01:00
Matt Kane 86ac15b784 fix(flue-review): elide oversized diff sections before staging for the model (#2393)
* fix(flue-review): elide oversized diff sections before staging for the model

* fix(flue-review): mark unreducible diff sections so the budget loop terminates
2026-08-10 09:22:46 +01:00
Matt Kane 4681b49034 feat(emdash-bot): reporter-verified pkg.pr.new fix loop (bot next-gen 4/5) (#2382)
* feat(emdash-bot): pkg.pr.new preview helpers, ask/PR renderers, artifacts push

Reader-side of the fix loop's preview build. `preview.ts` centralises the
full-ref pkg.pr.new install URL (which the poll probes and the ask advertises),
the fix/artifacts branch names, a bounded readiness probe, and the reap
branch-set. `comments.ts` gains the ask renderer (bot-ask marker, install
command, screenshots served from the artifacts branch with filename validation
and markdown escaping, reporter ask) and the confirmed draft-PR body.

The outbound push proxy now admits `bot/artifacts-<n>` alongside `bot/fix-<n>`
for the issue, and the fix agent reports screenshots and pushes the orphan
artifacts branch so the ask can render them.

* feat(emdash-bot): fix-loop preview polling, ask, reap guard, issue-close cleanup

The orchestrator now drives the fix loop end to end. On entering
preview_building it schedules a bounded pkg.pr.new poll on the DO alarm (one
probe per tick, ~10min budget); a 200 fires preview.ready, exhaustion fires
preview.failed back to the reproduced verdict. preview.ready composes the ask
from the persisted fix notes, screenshots, and the reporter login and posts it
before flipping labels, so a failed comment can't strand the issue in
awaiting-reporter with no ask.

Branch reaping now guards the fix branch behind an open-PR check and always
drops the artifacts branch (review flag F4), on the reject/expire/decline edges
and a new issues.closed cleanup path that bypasses the machine.

Also fixes a latent drain bug: a standalone side effect (runId undefined) with
no dispatch pending matched `undefined === pendingDispatch?.runId` and was
deferred forever. The poll-fired ask is the first non-dry-run standalone effect
to exercise it.

* style: format

* chore(emdash-bot): type the fetch mock via Parameters<typeof fetch> for typeless CI lint

---------

Co-authored-by: emdashbot[bot] <emdashbot[bot]@users.noreply.github.com>
2026-08-09 13:26:30 +01:00
Matt Kane 4ebeb0ac45 feat(emdash-bot): hybrid computer/sandbox execution layer + investigation skills (bot next-gen 3/5) (#2381)
* feat(emdash-bot): add execEnv seam over computer 0.1.1 + sandbox

Thin, testable seam wrapping the two investigation substrates: computer
0.1.1 Workspace (isolate/fs/git) and @cloudflare/sandbox (container). Routes
exec by target, bounds every op with a deadline, bridges VFS edits into the
container checkout, and confines every @cloudflare/computer touchpoint to one
module so the future computerd flip is a single-adapter change.

* refactor(emdash-bot): run execEnv over the getWorkspace RPC client

emdash is public, so the VFS read-clone needs no auth and runs via an
isolate git command; fs+runtime reach the DO through their RPC stubs, so the
seam lives agent-side. Drops the in-DO typed-git dependency and keeps token
minting confined to the container push path.

* feat(emdash-bot): land investigation skills as Flue 2 skill directories

Ports the repro-public/repro-admin/repro-api/diagnose/verify/fix leaf skills
and the investigate spine from the gen-1 .flue/skills content onto computer's
tool model, as flat SKILL.md directories the agent loads per mode. Replaces the
single investigate/instructions.md.

* feat(emdash-bot): wire investigate agent onto the hybrid execEnv

Adds the WorkspaceDO (computer Workspace + worker-shell isolate backend via a
LOADER binding) and swaps the investigate agent off useSandbox onto execEnv:
read/write/edit/ls/grep + an exec tool the model routes isolate-vs-container,
skills loaded per mode, VFS clone at setup. Container stays @cloudflare/sandbox.
Bindings: experimental flag, worker_loaders, WorkspaceDO DO + append-only v4
migration. Build + 107 unit + 35 integration green; typecheck at baseline.

* refactor(emdash-bot): drop the dead useSandbox deadline wrapper

withSandboxDeadlines wrapped Flue's useSandbox SessionEnv, which the execEnv
swap removed. withDeadline (still used by the classifier, orchestrator, and
execEnv) stays.

* fix(emdash-bot): make the VFS->container bridge stateless (review F1/F4/F9)

F1: derive the container sync set from the VFS itself (git status against the
checkout) before every container exec, instead of tracking dirty paths in
memory. Materializing before each exec -- not only at attach -- closes the
edit-after-attach gap (stale container source, and a fix push that omits
post-attach edits) and survives an isolate resume, since the VFS is the only
source consulted. Removes #dirtyPaths and the write-through path; the one-time
base checkout stays in the injected attachContainer.

F4: readArtifact takes a bare filename under .bot-artifacts/ -- rejects path
separators, '.'/'..', absolute forms, and a symlinked target.

F9: rewrite the module header to operative facts; the coherence claim is now
true because every container exec re-derives from the VFS.

* fix(emdash-bot): parse git status via NUL-delimited -z (review delta)

Non-z porcelain C-escapes and quotes special-character paths, so a delete of
such a path silently no-opped in the container (surviving stale file), and the
' -> ' rename heuristic misfired on paths containing that literal. Switch to
'git status --porcelain -z': NUL-delimited, never quoted or escaped, with
rename/copy old paths in a trailing NUL field (new-then-old). Adds rename and
non-ASCII regression tests.

* fix(emdash-bot): retry workspace client after a failed connection and mirror WorkspaceDO bindings in the test config

* fix(emdash-bot): idempotent cloneRepo, default exec target, diagnose-gated push capability; align skill docs with agent-owned pushes

* fix(emdash-bot): probe clone usability before reuse and give repro runs the fix skill

* chore(emdash-bot): widen the storage assertion lint directive for typeless CI lint

* chore(emdash-bot): regenerate worker types for the WorkspaceDO and LOADER bindings

* style: format
2026-08-09 13:26:29 +01:00
Matt Kane 7532335e9e feat(emdash-bot): maintainer-triggered investigation + fix-loop states (bot next-gen 2/5) (#2376)
* feat(emdash-bot): add investigation + fix-loop states to the machine

Adds the maintainer-triggered investigation lane (reproduce + diagnose,
no fix) and the fix loop (candidate branch -> preview build -> reporter
confirm -> draft PR, else reap): seven new states, the preview.* and
expire event families, and the diagnose/fix/openDraftPr/reapBranch
actions. Fully additive -- every existing state, event, and transition is
preserved. validateMachine passes: 17 states, 30 events, 87 transitions.

* feat(emdash-bot): wire investigation + fix-loop consumers

Threads the new machine states through the runtime:
- comments: readonly replies for the seven states, a needs_info agent
  comment, and target-aware CTAs for agent.reproduced/fix_ready so the
  verdict and preview lanes read differently from the legacy lanes.
- router: diagnose and fix modes in outcomeFromResult (verdict unclear ->
  needs_info; fix advances only when pushed).
- orchestrator: parseInvestigateMode learns diagnose/fix; runAction
  dispatches openDraftPr (draft PR) and reapBranch (delete bot/fix-<n>);
  a 14-day reporter-silence alarm fires expire.
- github: createPullRequest gains a draft option; adds deleteBranch.
- investigate agent: diagnose/fix modes plumbed, with diagnose-mode
  prompt guidance that forbids a fix.

* build(emdash-bot): generate and drift-check machine artifacts

The machine.ts header promised generated artifacts that did not exist.
Adds `pnpm bot:generate` (scripts/generate-machine.ts) which renders
machine.json (runtime snapshot) and BOT_STATE_MACHINE.md (states/events/
transitions tables + mermaid diagram) deterministically from machine.ts,
plus a vitest drift check that fails if the committed artifacts fall out
of sync. The generator uses explicit .ts imports so node runs it without a
bundler; allowImportingTsExtensions keeps tsc happy. The artifacts are
excluded from oxfmt so the generator owns their format.

* test(emdash-bot): cover investigation + fix-loop paths

Router unit tests: maintainer-only authority on investigate/fix, the
investigation verdicts, the fix loop through preview to the reporter wait,
confirm/reject/expire from awaiting_reporter, and outcomeFromResult in
diagnose/fix modes. Orchestrator integration tests drive the real DO and
machine through the happy fix loop (diagnosis -> fixing -> preview_building
-> awaiting_reporter -> confirmed draft PR), the reject and 14-day expire
reaps, needs_info from verdict unclear, and non-maintainer rejection.

* fix(emdash-bot): route a skipped fix run out of fixing

A fix-mode run that reports skipped emitted agent.skipped, which fixing
had no transition for -- the event no-oped and the run was cleared, so the
stale-run watchdog (which only covers runs that hang without reporting)
never fired. The item wedged in fixing permanently, escapable only by an
unadvertised bare reset. Adds fixing --agent.skipped--> blocked, mirroring
investigating, so every reportable outcome of a fix run is covered.
Regenerates the artifacts.

* test(emdash-bot): enforce validateMachine in the generator and drift tests

* style: format

* fix(emdash-bot): withhold the push capability from diagnose-mode sandboxes; typecheck the generator script

* chore(emdash-bot): run the generator with type stripping; refresh stale orchestrator and machine comments

---------

Co-authored-by: emdashbot[bot] <emdashbot[bot]@users.noreply.github.com>
2026-08-09 13:26:29 +01:00
Matt Kane 473119ad6b chore(emdash-bot): port to Flue 2.0.3 with Workers traces (bot next-gen 1/5) (#2375)
* chore(emdash-bot): bump @flue/runtime + @flue/vite to 2.0.3

Move the bot off the reviewed Flue 2 nightly onto the 2.0.3 release, and
align its bundled agents SDK dep with what @flue/vite ships (0.20.1). The
workspace hono override and cooldown-exclude pins are updated to match; the
nightly excludes are dropped since 2.0.3 is past the release-age cooldown.

* refactor(emdash-bot): port agent/tool/sandbox code to Flue 2 APIs

Flue 2.0.3 tightens several surfaces the bot uses:
- defineTool run() with an output schema must return { output } (envelope),
  not the bare value.
- init() handles split dispatch (returns a receipt) from read() (awaits the
  reply); the classifier now dispatches then reads with its timeout signal.
- DispatchReceipt.dispatchId is renamed submissionId.
- FlueEvent no longer carries dispatchId (observer drops it).
- SandboxFactory's primary method is createSandbox; createSessionEnv is
  deprecated, so withSandboxDeadlines must wrap createSandbox or the
  deadlines are silently bypassed. The unit test's mock follows suit.

Behavior is unchanged; these are mechanical adaptations to the new types.

* feat(emdash-bot): enable Workers traces

Flue 2's generated Worker entry installs content-on Cloudflare tracing by
default; this flag activates collection on the account. Content is enabled
(issues/PRs are public), matching the design's diagnosable-by-default goal.

* test(emdash-bot): raise workers-pool testTimeout for AI-binding warmup

The AI binding forces the vitest workers pool onto a remote proxy; the first
test to run pays the connection warmup and intermittently overran the 5s
default. Raise to 20s so the suite is deterministic.

* feat(emdash-bot): install explicit content-on Cloudflare tracing in app entry

Register instrument(createCloudflareTracing()) at module scope so content
capture is explicit rather than relying on Flue's default install. Content is
on (public issue/PR data); the API expresses on/off as omit/false, with no
true literal.

* fix(emdash-bot): bound classifier dispatch admission within the timeout budget

The dispatch/read split left handle.dispatch() (which resolves only on
admission) with no deadline, so an admission stall would hang classifyComment
past GitHub's webhook ack window instead of erroring. Wrap dispatch in
withDeadline and share one budget with the read so admission + settlement stay
within the 10s envelope.

Also trims narrative from the traces comment in wrangler.jsonc.

* test(emdash-bot): cover classifyComment dispatch path and fail read deterministically on an exhausted budget

* fix(emdash-bot): use a monotonic clock for the classifier budget; trim rationale comments

* chore(emdash-bot): commit generated worker types like the other worker packages
2026-08-09 11:51:07 +01:00
Matt Kane c8b0eb9ba1 fix(flue-review): cap tar entry size and honor pax linkpath overrides (#2388)
* fix(flue-review): cap tar entry size and honor pax linkpath overrides

* fix(flue-review): satisfy noUncheckedIndexedAccess in R2 instrumentation

* fix(flue-review): require a strictly octal tar size field
2026-08-09 07:04:03 +00:00
Matt Kane b30f7ac417 fix(flue-review): hydrate from the GitHub tarball instead of JS git (#2386)
* fix(flue-review): hydrate from the GitHub tarball instead of JS git

isomorphic-git pack indexing in the workflow DO stopped completing once
the repo's shallow pack passed ~16MB, silently stalling every review in
the hydrating stage until the watchdog killed it. The tarball of the PR
head SHA needs no git objects at all: stream it through the runtime's
native gzip DecompressionStream and untar into the workspace (ustar +
GNU longname + pax paths, symlinks included, archive root stripped).
The diff was already API-fetched; nothing downstream used the git repo.

Also keeps the hydration stage/R2 instrumentation added while
diagnosing: every stage and R2 operation logs start/end so the next
stall identifies itself.

* style: format

* fix(flue-review): harden untar path handling and extract it for testing

Review findings on the tarball hydration: the parser is the boundary
between an externally-supplied archive and the workspace, so entry
paths and symlink targets now reject absolute paths and any traversal
that would resolve outside the destination. The parser moves to
lib/untar.ts behind a narrow target interface with a vitest suite
covering files, directories, symlinks, GNU longname, pax paths,
truncation, and the escape rejections. Stale JS-git and incident
narrative trimmed from comments.

---------

Co-authored-by: emdashbot[bot] <emdashbot[bot]@users.noreply.github.com>
2026-08-08 22:00:23 +00:00
Matt Kane 582e89d138 Revert "chore(flue-review): enable Workers trace collection (#2372)" (#2384)
This reverts commit 3540e33c0f.
2026-08-08 17:30:25 +00:00
Matt Kane 3540e33c0f chore(flue-review): enable Workers trace collection (#2372) 2026-08-08 12:26:18 +01:00
Scott Buscemi 534f23884f fix(ui): move Comments/CommentForm to emdash/ui/comments subpath (#2039) (#2044)
* fix(ui): move Comments/CommentForm to emdash/ui/comments subpath (#2039)

Their <style> blocks were pulled into a shared, render-blocking CSS chunk
on every page that imported anything from the emdash/ui barrel (e.g.
PortableText), because Astro scans the whole barrel module graph. Splitting
them into a dedicated entry point keeps comment CSS off pages that don't
render comments, mirroring the existing emdash/ui/search entry point.

* fix(ui): keep barrel Comments exports as deprecated (#2039)

Address ascorbic review: add emdash/ui/comments without breaking existing
emdash/ui imports. Mark barrel re-exports @deprecated (remove in 1.0),
allowlist the subpath in the public-source guard, and sync template skills.
2026-08-08 11:39:42 +01:00
emdashbot[bot] 4255b04355 ci: release (#2244)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-08-06 00:24:20 +01:00
emdashbot[bot] 53dbf22555 ci: release (#2226) 2026-07-24 15:37:09 +01:00
emdashbot[bot] 09e5b5ca5b ci: release (#2176)
Auto Extract / Extract (push) Has been cancelled
CI / Typecheck (push) Has been cancelled
CI / Lint (push) Has been cancelled
CI / Version Check (push) Has been cancelled
CI / Changeset Validation (push) Has been cancelled
CI / Tests (push) Has been cancelled
CI / Smoke Tests (push) Has been cancelled
CI / Integration Tests (push) Has been cancelled
CI / Browser Tests (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
CI / E2E tests (1/8) (push) Has been cancelled
CI / E2E tests (2/8) (push) Has been cancelled
CI / E2E tests (3/8) (push) Has been cancelled
CI / E2E tests (4/8) (push) Has been cancelled
CI / E2E tests (5/8) (push) Has been cancelled
CI / E2E tests (6/8) (push) Has been cancelled
CI / E2E tests (7/8) (push) Has been cancelled
CI / E2E tests (8/8) (push) Has been cancelled
CI / E2E Cloudflare (1/8) (push) Has been cancelled
CI / E2E Cloudflare (2/8) (push) Has been cancelled
CI / E2E Cloudflare (3/8) (push) Has been cancelled
CI / E2E Cloudflare (4/8) (push) Has been cancelled
CI / E2E Cloudflare (5/8) (push) Has been cancelled
CI / E2E Cloudflare (6/8) (push) Has been cancelled
CI / E2E Cloudflare (7/8) (push) Has been cancelled
CI / E2E Cloudflare (8/8) (push) Has been cancelled
CodeQL / Analyze (actions) (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
Format / Format (push) Has been cancelled
Preview Releases / Publish Preview (push) Has been cancelled
Release / Release (push) Has been cancelled
Release / Sync Templates (push) Has been cancelled
zizmor / Run zizmor (push) Has been cancelled
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-22 11:47:04 +00:00
Matt Kane 7d28ce940a docs: exempt tool directives from the comment rules (#2183) 2026-07-21 19:19:29 +00:00
Matt Kane b828198646 fix(emdash-bot): persist agent results and authorize pushes (#2180)
* fix(emdash-bot): persist results and authorize pushes

* fix(emdash-bot): type orchestrator result binding

* fix(emdash-bot): harden push capabilities
2026-07-21 18:55:59 +00:00
Matt Kane 14e800b0cc fix(emdash-bot): deploy generated Flue worker entry (#2177)
* fix(emdash-bot): deploy generated Flue worker entry

* chore(emdash-bot): keep standard build scripts
2026-07-21 15:36:44 +01:00
emdashbot[bot] 3c555590ab ci: release (#1930)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-21 11:26:37 +01:00
Matt Kane 751c9d7d81 docs: strengthen agent guidance on logged-out query counts, comments, and test quality (#2155) 2026-07-20 22:09:04 +01:00
Matt Kane 6c50eb83bf chore(emdash-bot): migrate to Flue 2 agents (#2101)
* infra/emdash-bot: scaffold Cloudflare-target Flue app (Phase 0 spike)

The state-machine work from the closed feat/bot-state-machine branch is
being rebuilt on Cloudflare per .opencode/plans/0003-bot-on-cloudflare.md.

Phase 0 is the integration spike: stand up a Cloudflare-target Flue app
with the container-backed Sandbox integration and Workers AI binding,
prove the build succeeds, then validate end-to-end locally.

This commit lands the scaffolding:

- package.json / tsconfig.json mirroring infra/flue-review.
- wrangler.jsonc: AI binding, Sandbox + FlueRegistry DOs, container
  declaration, R2 workspace bucket. No Orchestrator DO yet (Phase 3).
- Dockerfile: minimal base for the spike (Node + pnpm + git + gh). The
  full toolchain (Chromium, agent-browser) lands in Phase 2 when we
  port the repro skills.
- .flue/cloudflare.ts: re-exports Sandbox DO, narrows Env.Sandbox type.
- .flue/app.ts: Hono root with Flue's standard /workflows routing.
- .flue/lib/classifier.ts: the shared classifier agent, defaulting to
  qwen3-30b-a3b-fp8 via the cloudflare/* binding-native provider id
  (no API key in scope).
- .flue/workflows/classify-command.ts: state-aware free-text classifier,
  ported from the previous attempt with cf-wai/* model strings replaced
  by cloudflare/@cf/* binding strings.
- .flue/workflows/investigate.ts: minimal stub agent that runs inside
  the container-backed Sandbox via cloudflareSandbox(getSandbox(...)).
  Returns structured classification only -- real five-stage pipeline
  lands in Phase 2.

Verified: `pnpm typecheck` and `pnpm build` clean. Both workflows
discovered. Sandbox container declaration parses. The Flue beta.5 +
@cloudflare/sandbox 0.12.1 + agents 0.14.5 + hono 4.12.23 dependency
set installs and resolves cleanly under the workspace's release-age
policy.

* infra/emdash-bot: Phase 0 spike validated end-to-end

Both halves work locally:

  classify-command (qwen3-30b via env.AI binding):
    POST /workflows/classify-command?wait=result
    -> {event:'retry', tokens:{input:1741,output:292}, model:'cloudflare/@cf/qwen/qwen3-30b-a3b-fp8'}

  investigate (glm-5.2 inside Cloudflare Sandbox container):
    POST /workflows/investigate?wait=result
    -> {kind:'bug', area:'admin', requiresBrowser:true, tokens:{input:1624,output:60},
        model:'cloudflare/@cf/zai-org/glm-5.2'}

The structural credential boundary works as designed: no API key is in the
agent's process address space at any point. The whole class of bugs the
previous attempt's eight review cycles patched is gone.

Fixes since first scaffold:

- Dropped process.env references from the agent definitions (Workers have
  no process.env; Flue rejected the AgentDefinition shape at runtime).

- Dockerfile: switched to a multi-stage build that COPIES Node + npm + pnpm
  from the official node:22.21.0-bookworm-slim image rather than downloading
  inside the sandbox base. The Cloudflare Sandbox base image has a broken
  CA bundle that fails curl -fsSL against nodejs.org with 'self-signed
  certificate in certificate chain'; copying across avoids any TLS in the
  final image. Symlinks for npm/pnpm CLIs get rebuilt because Docker COPY
  flattens slim's symlinks; chmod +x on the .cjs targets because they lose
  their executable bit during COPY.

- wrangler.jsonc: added Flue's workflow DO classes (FlueClassifyCommand-
  Workflow, FlueInvestigateWorkflow) plus FlueRegistry to new_sqlite_classes.
  Flue auto-adds the durable_objects.bindings in its merged .flue-vite.
  wrangler.jsonc but does not add the migrations; the user has to declare
  them sqlite-enabled. Same pattern as flue-review's wrangler.jsonc.

Phase 0 decision gate: PASS. Browser support (Phase 2) is the remaining
load-bearing piece -- the spike only proves the agent runs in a container
with Workers AI, not that it can drive Chromium for repro-admin/public
skills. That risk gates Phase 2, not the architecture choice.

* infra/emdash-bot: browser stack works in the Sandbox container

Phase 0 stretch validation. Extended the Dockerfile with Chromium's
runtime dependencies (libnss3, libatk, fonts-liberation, etc.) and
copied bgproc + agent-browser from the node-source stage. Added a
throwaway sandbox-probe workflow that runs a sequence of shell commands
inside the container to verify each piece.

Confirmed inside the Sandbox container:
- Node 22.21.0, pnpm 11.1.3, git 2.34.1, bgproc, agent-browser 0.30.1.
- 'agent-browser install' downloads Chrome 150 (~179 MB) in ~50s.
- Chromium launches and loads pages; agent-browser open/read works.

Two cleanup items for Phase 1 (not blockers):

- Chromium reinstalls every run because each Sandbox DO call gets a
  fresh $HOME. Phase 1 should either bake Chromium into the Dockerfile
  (~200 MB image growth) or persist /root/.agent-browser/browsers
  across runs via a volume / R2 cache.

- Locally, Cloudflare WARP intercepts TLS with a corp Zero Trust cert
  the sandbox base doesn't trust, so chromium shows cert warnings on
  page loads. This is dev-machine only and won't happen on real CF
  edges; safe to defer.

Decision: Phase 0 done. Browser-in-Sandbox works. Phase 1 (orchestrator
DO + webhook ingress + real investigate pipeline port) can proceed.

* infra/emdash-bot: port state machine + router + 32 unit tests

Ports machine.ts and router.cjs from the closed feat/bot-state-machine
branch into infra/emdash-bot/.flue/lib/. router.ts re-exports
findTransition from machine.ts (single source of truth) and uses
TypeScript-native exports instead of the CommonJS wrapper.

Sets up vitest in tests/unit/ with the full 32-case router suite ported
from node:test. All pass in 4ms. tsconfig includes tests/ for typecheck.

These are the substrate-agnostic bits of the bot logic; the OrchestratorDO
will wrap them with per-issue serialization in the next commit.

* infra/emdash-bot: OrchestratorDO skeleton + workers-pool test rig

Adds the per-issue Orchestrator Durable Object as the source of truth for
the bot lifecycle. The DO holds state, kind, currentRunId, prNumber, and
a bounded event log; webhook events route through event() and the
intrinsic per-instance serialization eliminates the PR-comment race that
plagued the Actions-based predecessor (PR #1606 cycle 4).

This commit is the SKELETON: resolve + persist + delivery dedupe + stale-
run discard + inert-state guard. GitHub side effects (label flip, comment,
PR ops) and workflow invocation land in the next commit alongside the
webhook handler, since they share the App-token-issuing helper.

Test infrastructure also lands here. Pure router tests stay in tests/unit/
(plain vitest, ~4ms). DO tests live in tests/integration/ and run under
@cloudflare/vitest-pool-workers against a real workerd isolate, with a
separate wrangler.test.jsonc + test entry that mirrors prod bindings but
skips Flue-generated workflow DOs (not exported by the test entry). Both
suites run via pnpm test; 32 unit + 7 integration tests pass.

* infra/emdash-bot: webhook ingress -> Orchestrator DO

POST /webhook/github verifies the X-Hub-Signature-256 HMAC against the
raw body, normalizes the GitHub payload into a NormalizedEvent, and
dispatches into the per-anchor Orchestrator DO via getByName.

Handles issues, issue_comment, pull_request, pull_request_review, and
pull_request_review_comment events. The classifier hand-off lives in the
DO; the webhook resolves bare verbs deterministically (parseCommand) and
flags everything else as needsClassify. Bot-author detection for the
in_review default-comment-event is intentionally deferred (defaults to
false, routes through classifier) until we have a known bot login binding.

Tests:
- 25 unit tests for actor classification + payload normalization (pure)
- 11 integration tests under @cloudflare/vitest-pool-workers: signature
  verify (the workerd-only timingSafeEqual), full SELF.fetch -> DO round
  trips for the deterministic verb path, free-text classify-pending path,
  duplicate-delivery dedupe, and signature/JSON rejection.

The core routes (health + webhook) live in routes.ts so the workers-pool
test entry can mount them without pulling in Flue's workflow routes
(those need workflow DOs the test wrangler does not declare). Production
app.ts still mounts both.

* infra/emdash-bot: GitHub side effects in OrchestratorDO

Ports readAppCreds + mintInstallationToken + JWT helpers from
infra/flue-review, adds bot-specific API helpers (addLabels, removeLabel,
postIssueComment, getIssueLabels), and wires them into the orchestrator's
event() path.

The transition path now: resolve -> applySideEffects (label flip + comment)
-> persistDecision. Side effects run BEFORE persist so a label-flip
failure leaves DO state unchanged and the next event retries; comment
failures are non-fatal and logged.

Tokens are cached in DO storage with a 55-minute window. Dev mode (no
GITHUB_APP_PRIVATE_KEY) cleanly skips all GitHub calls with a log line --
no exceptions, DO state still advances locally.

Adds GITHUB_OWNER + GITHUB_REPO as wrangler vars for the single managed
repo. Multi-repo support deferred; would need owner/repo plumbed through
NormalizedEvent and the DO signature.

The webhook normalizer now stamps anchorNumber onto every NormalizedEvent
so the DO can address the GitHub side. Tests stay green via empty PEM
binding -> readAppCreds returns null -> side effects skip.

* infra/emdash-bot: wire classifier into OrchestratorDO via ctx.exports

Free-text comments now invoke the classify-command workflow synchronously
via ctx.exports.default (the loopback service binding to the Worker's
default fetch handler, no service-binding config needed). The DO blocks
~1-2s on the classifier turn, then re-enters event() with the resolved
verb.

Removes the classify-pending placeholder outcome -- the DO now always
returns a concrete decision (transition / readonly / noop), where
classifier failures degrade to noop with a logged error.

Updates tests to the cloudflare:workers exports surface (cloudflare:test
is deprecated as of vitest-pool-workers v0.13).

* infra/emdash-bot: invoke investigate workflow on action transitions

Adds runAction() to the orchestrator: on a transition with decision.action
(investigate.repro / investigate.implement / investigate.revise), fetches
the issue context via the GitHub App token, generates a runId, persists
it as currentRunId, and admits the investigate workflow via Flue's
invoke().

Extends the investigate workflow to accept the orchestrator's input shape
(runId, mode, arg, issueTitle, issueBody) and call back into the right
OrchestratorDO via env.Orchestrator.getByName(...).applyAgentResult() on
completion. Phase 1 body is still a single LLM call; the 5-stage pipeline
is Phase 2.

Wires DO and Worker exports through .flue/wrangler-main.ts so wrangler
types can infer the class generics on Cloudflare.Env's DurableObjectName-
space bindings and the Cloudflare.Exports loopback service shape. The
file is type-only -- flue dev generates its own runtime entry and the
default fetch handler here just returns 500 if hit.

Drops the previous ad-hoc Env augmentation in cloudflare.ts. No tests
needed updating: the existing integration suite already exercises the
new action path (with creds-null degrading to a logged skip).

* infra/emdash-bot: post a status comment for readonly events

Status / help mentions used to be no-ops on GitHub. The orchestrator now
posts a short reply (current state + offered commands footer) when a
readonly event lands. No-creds dev mode still skips silently.

* infra/emdash-bot: cron tick via DO alarm

Adds self-arming alarms on the OrchestratorDO. The tick recovers stale
runs (currentRunId older than 30 minutes -> drop, allowing a retry) and
reconciles label drift between DO state and the live GitHub labels (the
DO is the source of truth; manual edits are healed).

The alarm self-rearms (every 60 minutes), bootstrapped from the first
event() call. applyAgentResult now clears currentRunId on completion so
stale-run detection doesn't false-positive on a finished run.

* infra/emdash-bot: wire openPr / closePr actions

Adds createPullRequest and closePullRequest helpers to github.ts, and
splits the orchestrator's runAction into runInvestigate / runOpenPr /
runClosePr. PR number is persisted to DO storage on open so close knows
what to target.

openPr will fail in Phase 1 (no fix branch exists yet -- the investigate
workflow's git push step is Phase 2). The runError surfaces in the
EventOutcome; DO state still advances.

* infra/emdash-bot: use DO state as source of truth in resolve()

The orchestrator was passing input.labels straight through to resolve(),
even when DO storage held a newer state from a prior transition. A
follow-up event (status check, retry, etc.) carried stale labels from
the webhook's snapshot and the router decided against them.

Now: if DO storage has persisted state, project it to labels via
projectLabels() and resolve against those. Falls back to input.labels
for first-time mentions where DO storage is empty.

* infra/emdash-bot: pre-clone repo + detect push in investigate workflow

The workflow now runs in two trusted phases around the agent:

1. setupSandbox(): before the agent starts, mint an installation token,
   write it to /root/.git-credentials (persistent credential store), put
   it in /etc/environment as GITHUB_TOKEN, configure git identity, and
   clone the repo into /workspace/repo. For revise mode, check out the
   existing bot/fix-N branch.

2. detectPush(): after the agent reports done, query the GitHub API for
   the bot/fix-N branch. If it exists, set pushed:true in the callback.
   The router's outcomeFromResult uses pushed to gate agent.fix_ready
   (fixed:true without a real branch demotes to agent.failed).

The agent now defaults to kimi-k2.7-code (the code-focused model) and is
told via instructions that the repo and creds are ready.

No-creds dev mode skips clone and push detection silently; useful for
sandbox toolchain smoke tests.

* infra/emdash-bot: outbound-proxy github auth + investigate skill

Switches the credential path from 'agent sees the token' to 'agent never
sees the token'. The Sandbox subclass declares outboundByHost for
github.com / api.github.com / codeload.github.com pointing at
authenticatedGithub, which mints a fresh installation token in the
Worker runtime, injects Basic auth (x-access-token format that works for
both git smart HTTP and the REST API), and forwards upstream.

allowedHosts denies everything except github + the registry hosts the
toolchain may need (npm + githubusercontent CDNs). enableInternet=false
makes that the only path out.

The agent now pushes directly: git clone/fetch/push to github.com is
transparent and the sandbox holds no tokens. The SKILL.md says so
explicitly to discourage poking at /etc/environment etc.

Wired in the investigate skill via the with-skill import attribute. The
orchestrator's investigate workflow import is lazy so the workers-pool
test pipeline (which has no Flue build plugin) doesn't try to parse the
markdown.

* infra/emdash-bot: fix Phase 2 sandbox setup; agent now sees a populated repo

Three bugs together prevented the sandbox setup from working:

1. interceptHttps defaults to false in @cloudflare/containers 0.3.x even
   though the April 2026 changelog says HTTPS interception is on by
   default. Override to true on our Sandbox subclass so outboundByHost
   handlers actually see github.com traffic (otherwise the proxy was
   blind to git clone over HTTPS).

2. harness.shell inherits the agent's cwd (/workspace/repo), which does
   not exist before the clone. Pass cwd: "/" so setup steps run from a
   directory that exists.

3. The setup script was a single .join(" && ") string containing an
   if/then/else/fi block, which is a bash syntax error ("if ... && else"
   never parses). Split into a typed steps[] array and run each via its
   own harness.shell call. Each step's exitCode is checked explicitly
   and stderr surfaces in the worker log on failure.

Adds x-emdash-dry-run: 1 header support: routes.ts forwards the flag
into NormalizedEvent.dryRun, and the orchestrator skips applySideEffects
(label flip + status comment) when dry-run. The workflow still runs in
full (LLM call, sandbox setup, push attempt). Lets local smoke tests
iterate without spamming labels/comments on a real GitHub issue.

Verified: dry-run repro against issue #1042. Setup steps all exit 0,
the agent's first command finds a populated /workspace/repo, the agent
runs real grep/find investigations against the cloned source.

* infra/emdash-bot: pnpm install in setupSandbox

Adds a final pnpm-install step to setupSandbox so the agent doesn't burn
turns rediscovering that it needs deps and figuring out which install
command works. --frozen-lockfile matches the lockfile in the checked-out
tree, which may differ between main and a revise branch.

The step is non-fatal: pnpm's post-install hooks can exit 1 in the
sandbox env (e.g. on missing build tools for native modules) while still
leaving node_modules populated enough to run tests. Failure is logged
with stdout/stderr tails but doesn't abort setup. Critical steps (clone,
checkout) remain fatal.

Bumps the install timeout to 10 min; clone gets 5 min. Updates SKILL.md
so the agent knows deps are pre-installed.

* infra/emdash-bot: allow pkg.pr.new + add native build toolchain

EmDash's pnpm-lock pins @lunariajs/core from pkg.pr.new; add it to the
Sandbox's allowedHosts so pnpm install can fetch it. Without this, the
install fails with ERR_PNPM_FETCH_520 (ContainerProxy returns 'Origin is
disallowed' status 520 for any host not in allowedHosts).

Add build-essential, python3, and python-is-python3 to the Dockerfile so
node-gyp can rebuild native modules (better-sqlite3, etc.). The previous
image only had ca-certificates + browser deps, which left node-gyp
unable to compile.

Also bumped the setup step failure log slice from 800 to 4000 chars so
node-gyp's actual error message is visible; the trailing summary alone
isn't enough to diagnose.

* infra/emdash-bot: human-readable bot replies

Replaces the bot-jargon transition comments ('Moved to working on retry
(investigate.repro).') with messages a reporter actually wants to read.
agent.fix_ready now includes a pkg.pr.new install URL (the existing
preview-releases.yml workflow auto-publishes for every push to
bot/fix-*), so reporters can pnpm-add the preview directly rather than
having to clone a branch. PR stays gated on .

Readonly status replies are state-specific now too instead of dumping
the verb list, and unmapped events get no comment at all (skip-post on
empty body).

* infra/emdash-bot: bump pnpm-install timeout to 15 min

Production sandbox network is slower than local docker; the 10 min limit
killed the install on a real run against #1623 before postinstall hooks
(better-sqlite3, sharp, workerd binaries) could finish. 15 min covers
the cold-cache case based on dev timings (~7 min) plus headroom.

* infra/emdash-bot: beefier sandbox + drop unused probe DO

- instance_type: standard-3 (2 vCPU, 8 GiB, 16 GB). The default lite (256
  MiB / 1/16 vCPU) was killing pnpm install on cold cache.
- NODE_OPTIONS=--max-old-space-size=6144 so node/pnpm processes can use
  the increased memory ceiling (mirrors what we bumped for emdash builds).
- Drop FlueSandboxProbeWorkflow. It was a Phase 0 toolchain probe that
  hasn't been invoked since; v2 migration deletes the DO class.

* infra/emdash-bot: add investigation tools to the sandbox

ripgrep, jq, tree, less, file, unzip, sqlite3. The agent fell back to
grep -rnH and similar in the first prod run because rg wasn't installed.
sqlite3 is useful when poking at D1/SQLite-backed tests.

* infra/emdash-bot: advance to failed when tick drops a stale run

A workflow can be evicted mid-run (DO hibernation, deploy rotation,
infra eviction) without producing a callback. The hourly tick already
dropped the orphaned currentRunId, but left DO state stuck on "working"
forever, with no way out except a manual reset. Synthesize an
agent.failed event after dropping the run so the state machine progresses
to `failed` and the reporter gets the failed-state comment.

* infra/emdash-bot: log agent turns via Flue observe()

Subscribes once at app startup to the Flue event stream and logs a
compact one-liner per run/turn/tool event. wrangler tail now shows what
the agent is thinking, not just the raw sandbox.exec commands -- much
easier to spot when the agent is stalled vs. mid-LLM-call.

* infra/emdash-bot: comment on agent.reproduced transitions

The agent.reproduced event maps to working -> blocked; we already had
text for the other agent.* events but missed this one. The state flipped
silently on #1589, leaving the reporter with just a label change and no
explanation.

* infra/emdash-bot: scoped GitHub API for agent; comments are agent summaries

The outbound proxy now signs api.github.com requests scoped to the
current anchor issue/PR. The agent can curl GETs anywhere on
api.github.com, POST comments and reactions on its own issue, and push
to bot/fix-<n>; writes to other issues, PRs, or repos are denied 403.
Anchor + repo are passed via ctx.params, installed per-run by the
workflow before the agent session starts.

Replaces the boilerplate bot-jargon comments with the agent's own
summary. User-driven transitions (repro / implement / confirm /
decline / reopen / reset / take_over / hand_back) no longer post --
the user just typed the verb, echoing it is noise. Agent transitions
post the summary verbatim, with structural footers (pkg.pr.new install
URL for fix_ready; "reply with steps" prompt for not_reproduced; etc.).

SKILL.md tells the agent the summary IS the comment, and to write it
to the reporter.

* feat(emdash-bot): migrate to Flue 2 agents

* fix(emdash-bot): pin Flue Hono resolution

* chore(emdash-bot): remove durability spike

* refactor(emdash-bot): harden type boundaries

* fix(emdash-bot): allow reviewed Flue nightlies

* fix(emdash-bot): address Flue 2 review feedback

* fix(emdash-bot): preserve investigation mode

* chore: add empty changeset
2026-07-20 10:50:00 +01:00
Matt Kane c786fd42a4 fix(flue-review): recover interrupted workflows (#2053)
* fix(flue-review): recover interrupted workflows

* fix(flue-review): improve check progress details

* chore: add empty changeset

* fix(flue-review): use EmDashBot name in checks

* fix(flue-review): tighten stalled review recovery

* fix(flue-review): clear trigger label on completion
2026-07-15 12:43:30 +01:00
Matt Kane 093940e547 fix(flue-review): make review runs observable and recoverable (#2019)
* fix(flue-review): add durable review observability

* fix(flue-review): harden review watchdog recovery

* fix(flue-review): satisfy watchdog lint
2026-07-14 18:27:44 +01:00
Matt Kane e8e8a2d94c chore(flue-review): switch reviewer to GLM-5.2 with reduced reasoning (#2014)
Move the PR review bot from kimi-k2.7-code to Workers AI's
@cf/zai-org/glm-5.2 and cap its reasoning effort at "low" so it stops
over-deliberating on straightforward diffs. Bump the per-attempt review
timeout from 20 to 30 minutes.

GLM-5.2 only carries the metadata flue needs (reasoning support, context
window) in pi-ai 0.80.x, which requires @flue/runtime and @flue/cli
1.0.0-beta.9. That release removed the FlueContext/createAgent<Payload,Env>
workflow model, so review.ts is migrated to defineAgent + defineWorkflow:
the agent holds the model, thinkingLevel, and cf-shell sandbox, while the
Action's run performs PR hydration and GitHub posting, reading bindings
back through getCloudflareContext() and keying the Workspace on the
per-run Durable Object id.
2026-07-13 14:26:42 +01:00
emdashbot[bot] baf4d8394f ci: release (#1871)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-10 17:29:37 +01:00
emdashbot[bot] c67e177b13 ci: release (#1856)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-07 19:01:37 +00:00
emdashbot[bot] 5f9a1ba769 ci: release (#1734)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-07 06:27:29 +01:00
emdashbot[bot] b291f1cc67 ci: release (#1700)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-02 07:32:03 +01:00
emdashbot[bot] 71a148db9f ci: release (#1677)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-07-01 17:08:52 +01:00
emdashbot[bot] bc9f1b6111 ci: release (#1668)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-06-30 15:30:39 +01:00
emdashbot[bot] e7552e0c44 ci: release (#1660)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-06-30 14:36:20 +01:00
emdashbot[bot] 761164105d ci: release (#1653)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-06-29 12:42:00 +00:00
emdashbot[bot] 647cfe4da0 ci: release (#1629)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-06-29 12:43:55 +01:00
emdashbot[bot] b66f697aa3 ci: release (#1592)
* ci: release

* format

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Matt Kane <m@mk.gg>
2026-06-25 19:35:58 +00:00
Matt Kane 7e4a9c915d fix(builds): raise Node heap for Workers Builds installs via NODE_OPTIONS (#1621)
The monorepo's pnpm install peaks above Node's default ~2 GB old-space
heap on the 8 GB Workers Builds container, so installs OOM
nondeterministically during deploys. Set NODE_OPTIONS=--max-old-space-size=6144
as a build var (wrangler vars are injected into the build environment)
on the demo and infra Workers that deploy via Workers Builds. No runtime
effect; workerd ignores NODE_OPTIONS.
2026-06-25 13:16:18 +01:00
Matt Kane 63ef4e8805 fix(flue-review): re-architect reviewer onto cf-shell, drop sandbox container (#1598)
* fix(flue-review): re-architect reviewer onto cf-shell, drop sandbox container

The @cloudflare/sandbox firecracker container was the source of the
reviewer's reliability problems: ~53% of runs errored (OOM at
256MiB/0.0625vCPU, persistent-bash-session death on malformed model
commands, per-command Worker->DO RPC stat-storms, and a wide
DO-eviction window from slow container hydration).

The review agents are read-only (search/read files, no installs, tests,
or builds), so the container is overkill. Move hydration to the
Worker-Loader-backed cf-shell sandbox: clone the base + fetch the PR
head via isomorphic-git into a Workspace whose git packfile spills to
R2, and expose a single `code` tool over state.* (searchFiles /
readFile / glob) to the agent. The base...head unified diff is staged
via the GitHub API (cf-shell git only exposes a changed-files list, not
a two-ref content diff).

Removes the Sandbox DO, Dockerfile, and @cloudflare/sandbox; adds the
worker_loaders (LOADER) and R2 (REVIEW_WORKSPACE) bindings plus the
v5-remove-sandbox migration. Validated end-to-end locally on PR #1484
(verdict produced, review posted, no container failure modes).

* style: format

* fix(flue-review): satisfy type-aware lint in webhook handler and code tool

Replace unsafe `as` narrowings from `unknown` (status query param, run
payload, code-tool params) with runtime guards, and avoid base-to-string
on unknown values when formatting run errors and unserializable code-tool
results. No behavior change.

---------

Co-authored-by: emdashbot[bot] <emdashbot[bot]@users.noreply.github.com>
2026-06-23 21:51:45 +01:00
emdashbot[bot] 6b036c43d0 ci: release (#1534)
* ci: release

* format

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Matt Kane <m@mk.gg>
2026-06-22 20:23:36 +01:00
Matt Kane 0bfab91765 chore: upgrade to Astro 7 (#1579)
* chore: upgrade to Astro 7

Bump the catalog to stable Astro 7 (astro 7.0.0, @astrojs/cloudflare 14.0.0,
@astrojs/node 11.0.0, @astrojs/react 6.0.0) and update templates, demos, and
packages for compatibility.

- Move route caching config from experimental.cache/routeRules to the stable
  top-level cache/routeRules keys (demos/cloudflare, infra/cache-demo).
- Drop infra/cache-demo's obsolete pkg.pr.new Astro preview pin in favor of the
  catalog; align its wrangler with the catalog (v14 adapter needs >=4.99.0).
- Externalize the bare zod import used by the type generator so EmDash sites
  build on Cloudflare under Astro 7.
- Remove the now-obsolete @astrojs/telemetry override and refresh the
  minimumReleaseAge cooldown exclusion for the Astro 7 release.
- Update @emdash-cms/cloudflare cache JSDoc to the stable top-level cache key.

* ci: update query-count snapshots

---------

Co-authored-by: emdashbot[bot] <emdashbot[bot]@users.noreply.github.com>
2026-06-22 16:42:59 +01:00
emdashbot[bot] 8b57af671c ci: release (#1516)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-06-17 20:42:46 +01:00