Built with ./build.sh bundle v1.0.0-rc3 on 61a0e74e: clean PostgreSQL smoke passed, full backend
16694/0/0 on Python 3.11 (delivered package set) and 3.13, image pip freeze equals constraints-release.txt.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The owner saved the translate refactor in WIP commit 233e3936
("chore(wip): save owner work in progress (2026-10-14)", parent 30907e66) and asked
for it to be moved onto master (7190786b) as its own change, reviewed on three axes
and merged only after the full verification gate.
Transferred verbatim with `git checkout 233e3936 -- <paths>` (no edits beyond the
fixes listed below, which are recorded in the transfer report):
backend/src/plugins/translate/** (61 files: module split of the LLM service and the
executor, batch classification/insert rows, executor delegates/dispatch/parallel,
llm prompting/records/recovery, scheduler execution, sql literals, sqllab
execution, target schema catalog, token constants, record outcomes/filter
forwarding, preview/prompt/sql/orchestrator modules, dictionary modules)
backend/src/models/translate.py + translate_identity.py, translate_job_runs.py,
translate_dictionary_preview.py, translate_metrics_languages.py (same 15 tables and
columns, split by domain behind a re-export facade; no migration needed)
backend/src/schemas/translate.py + translate_corrections.py, translate_dictionaries.py,
translate_jobs.py, translate_preview.py, translate_runs.py
backend/src/api/routes/translate/** (dictionary entries split out)
backend/tests/plugins/translate/** (5 new tests incl. import-boundary and terminal-state)
frontend/src/lib/components/translate/** (new Config* sections, CorrectionDictionaryPopup,
TranslationRunTerminalStatus, runOutcome helper, tests)
frontend/src/lib/api/translate/**, frontend/src/routes/translate/** (list, history,
dictionaries, job wizard and detail), translation stores and models, i18n translate.json
frontend/e2e translation specs + fixtures/helpers, vitest.translation.config.js,
playwright.translation-fixture.config.js
docs/tasks/2026-10-02-translation-*.md (7 plan/audit documents)
Fixes found while transferring (each has its own reasoning in the commit body below):
* tests/test_orchestrator_direct_db.py: the WIP replaced the silent direct_db ->
Superset fallback with a typed failure; the stale test asserted the old fallback and
is now pinned to the refusal (plus an end-to-end result assertion).
* docs/tasks/2026-10-02-translation-semantics-audit.md: the owner home path was
replaced with `$REPO_ROOT` so no personal path enters git.
Deliberately NOT transferred (not translate): settings refactor, dashboard-testing,
research scripts, docker/full-flow, .kilo, tools/, other docs.
The scope documents this work has to follow lived only as untracked files in the
main worktree, so the branch could not read the inventory it is required to
implement against - including
specs/050-mcp-interface/plans/2026-10-06-dashboard-testing-no-fallback-audit.md
(NF-1..NF-9), which AGENTS.md names as the tracking document for the
G-DASHBOARD-STRICT-EVIDENCE gate.
Copied byte for byte, sha256 verified per file (33 files, 0 mismatches):
- specs/050-mcp-interface/plans/2026-10-04-*, 2026-10-05-*, 2026-10-06-*.md
(19 files);
- docs/matrix/traceability/* (14 files);
- AGENTS.md, whose no-fallback section and gate reference the branch lacked
entirely (branch file was a strict subset: sha256 4782b7d6934ed7f2 both sides
after the copy).
Nothing in the main worktree was modified and master was not touched. The
2026-10-07 plans were already tracked in the branch and identical, except
2026-10-07-stage1-current.md, which differs because this session has been
recording status in it.
Discover dashboard filters, datasets and metrics from a parsed reference URL; capture and review baseline candidates with source provenance. Improve scenario DAG and run result views, add isolated browser coverage, and align contracts and ADRs.
Add 2026-09-08 production gap/spec-coverage/refresh-plan and dashboard
scenario E2E plan/report, axiom-mcp feedback, and 2026-09-11 data-team
maintenance dev-test run notes.
Source: live external MCP run against ss-prod Sales Dashboard (docs/2026-09-07-sales-prod-mcp-run.md) proved the initial-bootstrap chain externally unreachable: register_draft_pack requires a principal-owned AgentRun but no MCP operation created one after the chat decommission; the vertical E2E masked the gap with a raw-ORM prerequisite seed.
T029i: MCP create_agent_run/get_agent_run (mcp_server/tools_agent_run.py) over Services.AgentRuns.Service.Create — REST-parity EXECUTE/READ permissions, human-only, server-pinned UIContext, idempotency-key replay; catalog 2.1.0->2.2.0; MCPX-FR-027 external-reachability invariant pinned; initial-scenario E2E converted to the fully external chain (zero non-MCP seeding); strict-xfail pin flipped as designed, unmarked and hardened (E2E-EXT-001 CLOSED).
T029k: ScenarioGraph.CapabilityAuthority — truthful capability facts derived from the authoritative DashboardQueryModel (mutation-context capabilities never derived), derived-wins merge over caller declarations, single choke point wired into MCP inspect_scenario / inspect_dashboard_context and REST api_compile_scenario; CAP-001 classification-fix test on the sales-shape fixture (B02-B04/T01-T03 automated, C04-C06 unsupported, unsafe-mutation cases legitimately human).
T029l: disposition vocabulary clarity — RU/EN labels name the persisted outcome (confirm->passed), confirm restyled bg-destructive->bg-primary, decide_checkpoint description carries the immutable outcome table; lifecycle mapping and API vocabulary unchanged (DISP-001 CLOSED).
Decision memory: ADR-0024 (IMPLEMENTED, 4 rejected alternatives incl. no-AgentRun boundary and implicit auto-create) + README registry; 050 MCPX-FR-027/028/029 + release-gate rows + Clarifications session 2026-09-07; 038/044/045 field-run amendments -> IMPLEMENTED; WORKSTATE checkpoints (plan round + execution round).
Pre-existing HEAD regressions surfaced by the first full-suite rerun since 4d5ef6be/58c5ae39 and fixed: (1) stale SC-007 resource pin — canonical identifier is the post-redirect /mcp/ (code + twin pin aligned since the batches; test_mcp_client_flow_http pin updated with rationale); (2) app-lifespan tests re-entered the run-once StreamableHTTPSessionManager module singleton — autouse fresh-transport-app fixture (production lifespan runs once per process; singleton stays correct there).
Gates: full backend suite 11357 passed / 243 skipped / 1 xpassed / 0 failed (first green full run since the batches); MCP+catalog slice 70 passed; capability slice 67 passed; frontend vitest 3507 passed (206 files), lint 0 errors (364 baseline warnings), build OK; ruff/compileall clean; anchors balanced; scoped git diff --check clean. INV_7 watch: tools_scenario.py 508 LOC and routes scenario.py 442 LOC flagged for the next decomposition pass (new code lives in new modules 155/236 LOC).
OPEN: T029m / E2E-EXT-002 — live-stand replay of the sales scenario through the full external chain. Not included (foreign uncommitted workstream): translate/migration integration tests, _job_routes.py, .kilo/agent-manager.json, specs-036-050-20260907-111314.md.
Workers are continuable long-lived children: spawn once, refine in place
via send_message as the feature evolves; a worker's own session persists
and compacts independently. Re-spawn only when the context is poisoned.
- skill §3: delegation tree rewritten — "refine, don't re-spawn"
- skill §5: "refine, don't re-spawn" coordination rule
- skill §7: stalled worker → send_message (keep context), fresh spawn
only for poisoned context
- contracts: Self.Worker.Implement is "long-lived, refined in place";
add long-lived invariant
Drop the "never read raw files" rule — it was a false economy. The
architect's context is large and auto-compacting, so reading is cheap and
necessary for decomposition and verification. The real boundary is
EXECUTION (edits/builds/tests) stays with workers, not READING.
- skill §1/§6/§10: "read freely" replaces "never read raw files";
prefer read_outline/search_contracts to locate, read/grep/glob to understand
- @RATIONALE reframed: reading is cheap; only DECISIONS must not live
solely in context (they go to files)
- contract: invariant becomes "reads freely for decisions, delegates execution"
Session-log review found the orchestrator diverging from its own design.
Encode every divergence as a rule + invariant:
- no polling: get_goal/list_agents are state tools, not completion checks
(settlement/report are the signals) — was 101 get_goal + 98 list_agents
- no raw reads: structure via read_outline/search_contracts; file CONTENT
is delegated (was 77 read vs 1 read_outline)
- <RESULT> enforcement: a worker result with no envelope is blocked
(was 4/19 envelopes)
- closed role taxonomy: only Implement/Verify/Curate (was ad-hoc
"code reviewer"/"auditor"/"adversarial")
- fork semantics: fork inherits MY context, not a stalled worker's;
no "takeover" via fork
- interrupt only to redirect; let workers finish (was 7 interrupts)
- decision memory written by me to files (was zero file writes)
- skill hygiene: load self-orchestration once; never load worker skills
- cross-workspace: point Axiom at the target or delegate all reading
Child subagents join the parent's preset composition, so by default they
inherited the orchestrator persona AND the delegation tools — and drifted
into orchestrating instead of working (observed: a "worker" called
list_agents/get_goal/send_message and spawned its own grandchildren).
Fixes:
- preset: subagent/subagent_fork now carry a role-agnostic worker `persona`,
`toolFilter.deny` for all delegation/coordination tools, and `maxDepth: 1`
(children cannot spawn grandchildren) — hard enforcement at the boundary
- skill: every worker prompt opens with a mandatory role-reset block
- contracts: Self.Worker.Implement/Verify gain a LEAF invariant (no subagents,
no delegation tools)
sqlparse raises SQLParseError above MAX_GROUPING_TOKENS=10000 tokens
(~25KB of typical SQL). The try/except fallback already handled it, but paid
~1s per oversized SQL for a parse doomed to fail. Add _SQLPARSE_SKIP_THRESHOLD
(30k chars) to bypass sqlparse for oversized text (~15x faster, 1.2s->0.08s for
a 212KB SQL) while keeping literal filtering for SQL under the threshold.
Tests: oversized-SQL skip-threshold behavior.
Discovery of virtual datasets now works, but a runtime blocker remained: any
virtual dataset whose SQL exceeds sqlparse's MAX_GROUPING_TOKENS (10000 tokens)
raised SQLParseError 'Maximum number of tokens exceeded (10000)' from
extract_tables_from_sql_span, which is called unguarded in the scan loop — one
oversized virtual dataset aborted the whole maintenance preview/start.
- extract_tables_from_sql_span now wraps sqlparse.parse + token walk in
try/except and falls back to regex-only extraction (keeping all schema.table
matches) instead of raising, so huge SQL no longer fails the scan.
- Tier-1 virtual filter uses value "" (not None) so the sql is_not_null filter
passes Superset's rison schema instead of always falling back to a full scan.
Tests: huge-SQL fallback (extractor) and huge-virtual-dataset scan resilience
(scanner). ADR-0020 updated with Decision 3.
Virtual (SQL) datasets were never matched, so maintenance discovery returned
0 affected dashboards. Two defects fixed:
- find_affected_dashboards filtered by is_sqllab_view, which is NOT a
filterable column in Superset's dataset list API (absent from search_columns),
so the query was rejected. Now discover virtual datasets via the filterable
sql column: primary server-side 'sql is_not_null' filter with a client-side
non-empty-sql scan as fallback (best-effort vs pagination cap), dedupe by id.
- AsyncAPIClient.request never called raise_for_status(), so rejected filters
(HTTP 400) were returned as bodies without a 'result' key and surfaced as
'Found 0 datasets', dead-coding the filtered->full-scan fallback. request()
now raises on non-2xx via the existing error mapper.
Tests cover both virtual-scan tiers, all fallback paths, the raise behavior,
and an end-to-end match with the real sql_table_extractor on production SQL.
Documented in ADR-0020.