agent.await and agent.spawn{await:true} now return immediately when
children are still running: the session closes, runAgent registers a
wake signal in agent_run.await_wake and waits with waitForFact without
holding an io/agent worker slot. A child that settles (terminal or
waiting) signals the parent's registered fact, so the parent resumes at
once instead of polling; the suspended call replays and the child
report becomes the tool result. agent.spawn is registered replay-safe;
a suspended spawn is recorded as failed in the ledger so the replay
re-runs it against the same child.
Migration 0037 also adds the admin_recovery_code, admin_passkey and
webauthn_challenge tables used by the account work.
E11 asserts the parent is suspended with no run held by any worker
while it waits, and covers spawn{await:true} end to end.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
pi.provider / baseUrl / model / thinkingLevel / apiKeySecretRef are now
DEPRECATED_SETTINGS_FIELDS: kept in the schema for stored JSON, dropped
from PATCH /settings and from the settings sections, never read by the
server. runAgent fails with a clear message when no upstream is set.
The agent demo gate checks the default upstream provider; e2e seeds a
fake upstream as default. OpenAPI summaries say Agent upstream.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
- agent_run gains depth / spawn_reason (0029); agent_run_event types
subagent_spawned / subagent_event / subagent_completed
- agent.spawn (propose, medium, replay never): allowlist ⊆ parent, mode not
above parent, budget carved from parent's remainder, idempotent per run+input;
settings.pi.subagents {enabled, maxConcurrent, maxDepth} (subagentsEnabled kept as alias)
- child runs claim a concurrency slot under an advisory lock (waitForFact while
queued); agent.await polls business tables without calling the model
- parent abort cascades to all descendants; parent runtime budget counts
descendant usage; child events mirrored into the parent stream by parent seq
- authorize caps every child call by all ancestors' allowlists/kinds
- session page shows parent link, inherited info and the subagent tree
- e2e E11; runbook section on subagents
Co-Authored-By: Claude Opus 5.5 <[email protected]>
- settings.agent.autoInvestigateMode investigate|recover, investigateMaxAttempts, recoverVerifySec
- new capability download.recheck (execute, replay never): qB force recheck / resume, no source swap/delete
- autoInvestigate moves to agent/investigate.ts: recover mode runs execute with a recovery allowlist
only when an active grant (published policy if bound) covers the recovery actions; otherwise degrades
to read-only investigation and leaves suggestion + recheck option on the decision
- runAgent verifies recovery against business facts (download_task/task/source_release) before finalize;
verified -> decision resolved by system:auto-recover, run summary '已恢复(系统核实)'; otherwise stays
awaiting_user; per-root-cause attempt cap
- e2e E6: missingFiles -> download_failed -> recheck -> verified; no grant degrades; swap rejected;
dedupe; attempts exhausted; budget exceeded keeps attention
Co-Authored-By: Claude Opus 5.5 <[email protected]>
- POST /approvals and PATCH /approvals/{id} require a console admin session
(EndpointDef auth:"session"); API keys incl. admin scope get 403, so an
organize.execute key can no longer approve its own plan (S1)
- tests for single-use approval checks: expired, revision/payload hash
mismatch, consumed, revoked, pending/rejected, plan mismatch; re-approve
after plan change succeeds once and cannot be replayed (S4)
- one redact key table in @umt/contracts shared by server logger and agent
redactForModel: rsskey, torrent_pass, authkey, downhash, c_secure_pass,
passkey variants, x-api-key, cookie headers, nested objects/arrays (S2)
- TMDB network errors: message and cause redacted via redactUrl (S3)
- web Agent ?mock=1 only in DEV builds or when pi.provider is fake (S7)
- EndpointDef auth annotations for /auth/*, asserted against
PUBLIC_AUTH_PATHS (S10); doc drift fixes (S11)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
- Agent page uses contracts (AgentRun/AgentRunDetail/AgentGoalReport) instead of a local
mirror; ?mock=1 stays as an explicit demo switch; run snapshot refreshes on agent.run_status;
stream auto-follow only while the user stays near the bottom (abort stays reachable)
- settings: Pi provider select incl. fake, new Agent runtime card (budgets, fakeScript)
- download trace uses /tasks?subjectId= and /organization-records?downloadTaskId= instead of
time-window engine run matching and path matching; new business-task tab with cancel/retry
- workbench download dialog posts /acquisition-plans and shows per-slot rejection reasons
- preference tag revision history; subscription search by title/kind; identity/alias/subscription
lists show entity titles; slot cards show current asset summary; policy preview sample titles
- DecisionSummary / IdentityRevisionList / ReleaseIdentityResult / TaskAccepted / PolicyPreviewSummary /
OrganizePlanArtifactContent taken from contracts
- docs: SSE for console (cookie) vs GET /events?after=&limit= JSON replay for API keys
Co-Authored-By: Claude Opus 5.5 <[email protected]>
- Capabilities: all 14 registered (AO: inventory.query, download.plan/submit, organize.plan/execute,
policy.preview/apply; agent: task.inspect/retry/cancel); startup asserts count == 14.
Registry injects server-side authorize (automation_grant by action/scope/policy version/budget,
one-shot approval bound to plan id + payload hash + revision + expiry; model claims ignored;
automation switch), audit_event, server idempotency keys and a capability_invocation op ledger
(migration 0021) used for crash reconciliation. download.plan creates draft plans only;
download.submit promotes draft -> reserved after authorization.
- Agent session API: POST/GET /agent/runs, GET /agent/runs/{id} (events by seq, messages, report),
POST .../messages (wake), POST .../abort; automation-grants, approvals, capabilities invoke, tasks.
- runAgent task: Pi or fake provider from settings (apiKey via secrets), events persisted to
agent_run_event then published, resume + ledger reconciliation when pendingOperations > 0,
waits for goal-linked downloads/imports and reports from business tables (submitted != imported).
- Background triggers: decision.created -> bounded plan_only investigation (dedupe per decision);
decision.updated(resolved) -> resolveDecision executes chosen option.
- W2 closure: all OpenAPI routes registered in contracts api.ts (+ subset test); TMDB key from
settings secret_ref with env fallback; PUT /sites/{id}/credentials documented as alias of
/site-accounts; completion events documented as existing status events.
- e2e (real PG + OpenWorkflow + testkit mocks): RSS->library, agent delegation with grant/deny,
background continuation, worker kill -9 recovery (single qB add), auto investigation dedupe.
Co-Authored-By: Claude Opus 5.5 <[email protected]>