OpenWorkflow 0.10.1 claims any run regardless of workflow name and fails
unregistered ones with 5s-5m backoff; filter the claim SQL by name@version.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The business row settles before the engine marks the workflow completed; under CI load the
window is a few hundred ms and the direct assertion flaked.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Logs in, opens every console route (detail routes resolved from list endpoints), fails on
console errors, uncaught exceptions or 4xx/5xx API responses, and screenshots each page.
Uses playwright-core with the local Chromium; documented in README.
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]>
- sites + /sites/:siteId: organized view with snapshot-first release list, inventory overlay,
candidate reasons, volatile-field recheck, stale marking that keeps existing data, live search,
unified download entry; origin view placeholder (M2)
- sources: feed CRUD/enable/fetch/reset, cursor/health/gap hints; per-site snapshot history
- tasks: download tasks with pause/resume (threshold pause cannot be bypassed), plans,
cache volume thresholds and cleanup, business timeline (observation → plan → download →
organization → agent/engine)
- organize: record list/detail with file-level results, manual organize with dryRun preview
- agent: session list/page and layout drawer with context prefix; streaming events,
tool cards, rejection alerts, compaction, budget meters, model text vs server report;
mock switch (?mock=1) until W2-D endpoints land
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]>
- /login: setup/login/TOTP states driven by server error codes, fixed-height error slot
- console layout: GET /auth/session gate, redirect to /login, account popover (change password, logout)
- home: six dashboard sections with SSE-driven refresh, automation switch and read-only reconcile toggle
- settings tabs: downloaders, media servers, library roots, path mappings, site credentials,
API keys (one-time plaintext), Pi upstream, cache/organize/retention/budget, automation
- engine: runs list (status/name filters, cursor paging, stats tiles), run detail (step timeline,
json payloads, signals, cancel)
- audit: filterable list with detail sheet
- vite: allow repo root in server.fs so deno-installed deps under node_modules/.deno load in dev
Co-Authored-By: Claude Opus 5.5 <[email protected]>
- library list (kind/status/search, cursor paging) and detail: paths and roots, external identity
mapping with lock, field-level metadata sources and locks, slot cards with rejection reasons,
content units (provisional flag), downloads with verification; remap/lock/refresh/merge actions
- subscriptions: list/create/update, slot rules editor (hard/soft/upgrade/completion),
policy revision draft -> preview -> publish (grant warning) -> rollback
- preferences: tag CRUD, disable/enable, suppression records and lift, history timeline
- inbox: grouped by entity and kind, evidence/suggestion/impact/preview, resolve options, SSE refresh
- identity: pool assign/dismiss/retry, external identity revisions and lock, title alias management
- all responses validated against contracts zod schemas
Co-Authored-By: Claude Opus 5.5 <[email protected]>
main.ts starts the PG-backed SSE bus (api/worker processes now see each other's events)
and stops it on shutdown; bootstrap passes ctx.events to the settings reader so
settings.changed invalidates every process's cache.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
New @umt/mapping (depends on domain + contracts only): download status + pause reason,
evidence level / media kind, identity resolution status, slot status / spec columns /
evaluation, ParsedRelease <-> source_release.parsed, SiteRelease <-> source_release,
PathBinding, OrganizePlan -> organization_record / file results / organize.plan output.
Tables are Record<union, ...> so adding a value on either side fails typecheck or tests.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
tasks_run_meta/tasks_fact/tasks_op_ledger move into packages/db (if not exists, old
tasks_migration tables dropped); packages/tasks/migrations and migrateTasksTables
removed, tests migrate their schema with @umt/db. agent_run_event(run_id, seq, type,
at, payload) with (run_id, seq) primary key; types regenerated, db-sync covers it.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
With the default hash="size", a target that already existed with the same
size but different content was treated as "already copied" and the source
was deleted (data loss; REQ §2.1 cleanup needs verified import). The
pre-existing-target comparison now always uses sha256; test covers the
same-size/different-content case with default options.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Plan §5 has W2-B emit and W2-C consume `release.resolved`, but EventType /
EVENT_PAYLOADS lacked it, so the two parallel subtasks would each invent a
payload. Minimal payload: sourceReleaseId, observationId, mediaEntityId,
contentUnitIds, evidenceLevel (contracts EvidenceLevel).
Co-Authored-By: Claude Fable 5.1 <[email protected]>
The relay only looked at published_at and ignored the ADR-002 §2.1 columns
added in db 0002_foundation: rows stayed status='pending' forever after
dispatch, failures were retried every tick without backoff, and the
row-level idempotency_key was never used as the engine enqueue key.
- claim status='pending' AND next_attempt_at<=now()
- enqueue with idempotency_key (fallback outbox:<id>)
- success: status=dispatched, published_at, attempts+1
- failure: attempts+1, exponential backoff (cap 5 min), last_error; dead at maxAttempts
- test helper table now mirrors db 0001+0002; tests cover backoff and dead
Co-Authored-By: Claude Fable 5.1 <[email protected]>
- rss: port of MP RssHelper._parse_impl/get_rss_link semantics with safe
XML (entities off, DTD/ENTITY rejected, size/item caps), ETag/Last-Modified,
backoff + Retry-After, circuit breaker with manual reset, passkey redaction,
overlap-window GUID+digest dedupe
- sites/spider: TS port of MP SiteSpider (indexer schema, search URL builder,
field DSL, filters, Jinja templates via nunjucks, login-page detection);
audiences definition hand-written as JSON; raw category id preserved;
shared per-site token bucket
- sites/mteam: port of MP MTorrentSpider (params, result mapping, promo
factors, genDlToken flow) without embedding the API key in enclosures;
business code/message checks
- testkit: mock RSS server, mock NexusPHP site, mock M-Team API
- docs: W1-3b migration mapping appended to porting ledger
Co-Authored-By: Claude Fable 5.1 <[email protected]>