- search(..., scope=code) restricts to 15 programming domains
(official docs, GitHub, registries, Stack Overflow, CVE/NVD):
native include_domains/search_domain_filter where supported
(Tavily, Exa, Perplexity), post-filtering for all providers
(Brave, SearXNG, DuckDuckGo have no native filter).
- web_fetch now uses fetch_best: Tavily extract, then Exa
contents, then direct fetch; both-fail errors name both
failures, direct-fetch 403 under the egress whitelist is
fail-closed, not bypassed. Default general scope and direct
fetch_url behaviour unchanged.
- MCP web_search gains scope enum (general/code); docs updated.
- Tests all mock HTTP, no real keys.
Deploy restarts kill running tasks: the worker marks them
interrupted (worker_shutdown on graceful exit, sweep on stale
reclaim), and auto_resume_interrupted used to accept goal tasks
only, so every non-goal task killed by a deploy stayed
interrupted forever unless a human retried it (the 2026-10-30
demo task died this way).
Now worker_shutdown/sweep interruptions are re-queued for
non-goal tasks too: the platform killed the task, so the
platform re-queues it. The re-queue is a fresh run, not a
breakpoint resume: goal_resume_pending is forced to 0 and any
stale resume_message is cleared, so the new run cannot be
hijacked by the goal-resume path or an old continue message;
files in the same worktree persist. All existing guards stay:
user pause, coordinator orphans, quota (still goal-only),
backoff, the 3-strike stall guard (non-goal tasks have no
checkpoints, so each platform re-queue counts as no-progress),
and the auto_resume_max cap. Other non-goal reasons (NULL,
quota, user cancel) still do not auto-resume.
- AutomationPanel rows now show title, prompt content (160-char preview with expand/collapse), repo_url, last/next run, run_once badge and cancelled time.
- Active automations get an inline edit form (name/prompt/interval/repo) that PATCHes only changed fields via the existing automation_update endpoint; backend semantics unchanged (no last_run_at reset, cancelled stays terminal).
- Rebuilt cloud/console.html with tsc + vite (build green); automation python tests 18/18 OK.
Stale bridge state used to end the stream on the first stale read,
so every round gap and every worker restart killed the watch (the
2026-10-30 demo watch died this way when a 15:03 deploy restarted
the worker). Now a stale state switches to a waiting heartbeat
every 5s while the task is still alive (running/queued/paused/
interrupted), and frames resume when the next round's MCP starts
polling. The stream ends only on a terminal task state, a missing
task row, or 10 minutes of continuous staleness. The panel shows
a waiting status and keeps the last frame. Also force-close the
SSE connection on stream end: HTTP/1.1 keep-alive otherwise left
terminal streams hanging with no EOF.
- cloud/tree.py: structured worktree tree (dirs first, ignore
.git/node_modules, symlinks not followed, entry/depth
truncation flags, text render for injection)
- GET /tasks/{id}/tree with /files auth + worktree resolution,
max_depth 1..5, max_entries 1..500, escape 400, missing 404,
cloud/cross-host 409
- MCP get_task_tree translating to the new endpoint
- worker first-round injection of a repo-checkout top-level
snapshot (2 layers, 120 entries) after repo resolution,
labelled as checkout snapshot not worktree; skipped for
coordinator/resume/fork, silent when no host source
- docs/project-tree.md; tests for tree, endpoint, injection,
MCP translation
- G0/G0.5: repo freeze items (new vs existing, owner/repo, default branch,
visibility); new-repo creation and first commit are G1 prerequisites.
- One branch per thread (feat/swe/<phase>-<role>-<short>), never push main
directly, never force-push main; sync main before PR, coordinator
resolves conflicts, never silently.
- Delivery requires a PR with scope, contract version, test evidence,
known issues and linked todos/PRD items; no PR number means not done.
- Merge gate: Checks green, directory ownership pass, frozen contract
version, coordinator approval, no unresolved review comments.
Branch protection (require PR, require Checks, block direct push) is a
GitHub repo setting; if unset, coordinator records it as risk and
enables it, never pretends it is protected. GET /tasks/{id}/pr/checks
is read-only diagnostics, never reruns or approves.
- Merge commit by default; merge record holds PR number, merge commit
hash, CI run link and executor; delete remote branch after merge.
- Per-client release tags (e.g. v0.1.0) from merged PRs; rollback is
revert or redeploy previous tag, never force-push rollback.
- Security: tokens/keys never in code, commits or command lines;
token only into subprocess env (cloud/pr.py GIT_TOKEN pattern);
.gitignore covers secrets and local config.
- Main text and appendix (coordinator, client, acceptance) updated in
sync; appendix travels inside SKILL.md for seeding.
Add cloud/skills/software-engineering/SKILL.md (686 lines, v0.2, appendix with 9 role templates travels inside SKILL.md because skill_seed only copies SKILL.md, not templates/). Update skill pack tests: EXPECTED set and real-pack list now include software-engineering, plus an explicit seed test asserting it lands at skills/software-engineering/SKILL.md, contains the appendix, and tenant edits are never overwritten. One-line wording tweak in the architect template avoids the existing secret-scan false positive on the substring sk- inside agent-task-contract.md; deployed file sha256 bd0436399ac05c6131b9281dad00973e50d13540e4c56ad21f21e2b5209bae8e (40759 bytes, 686 lines).