Commit 8646516eae0cde505e197a7e6470822dcafadf7d

Authored by graphlemon
1 parent bd13bd26

graphlemon: auto-commit uncommitted changes for 90c6ca9d-21eb-4678-ab12-2e2f5bd0…

…11fd-main-checkout-drift
.claude/agent-memory/planner/MEMORY.md
... ... @@ -4,3 +4,4 @@
4 4 - [deploy_health_check.py HTTP-timeout comment missing](project_deploy_health_check_http_timeout_comment_missing.md) — HEALTH_CHECK_HTTP_TIMEOUT (line 26) has no comment directly above it, unlike its sibling STARTUP_TIMEOUT; distinct open fact, don't conflate the two
5 5 - [artifact overview click-through bug: RESOLVED](project_artifact_overview_click_through_bug.md) — re-verified 2026-08-06, all 3 gaps fixed (data-artifact-id, #/artifacts/:id route, mountArtifactBrowser seeding); re-check before trusting "resolved" long-term
6 6 - [org-strip click-through bug: 3 render sites, not 1](project_org_strip_click_through_bug.md) — renderOrgStrip (dashboard), v_task_detail's inline org-strip, and #/graph's renderOrgGraphTopology all share the same no-click gap; DAG/log/artifact display mechanisms already exist and must be reused, not rebuilt; no new backend endpoint needed
  7 +- [run-history click → missing run detail page](project_run_history_click_missing_detail_page.md) — gc_runs_list click only switches task selector, no #/runs/:run_id route exists (documented trade-off, not a bug regression); DAG-panel+log-viewer funcs are run-object-generic and reusable verbatim; backend needs one new by-run_id query since _work_nodes_for_run already exists keyed by run_id
... ...
.claude/agent-memory/planner/project_run_history_click_missing_detail_page.md 0 → 100644
  1 +---
  2 +name: project-run-history-click-missing-detail-page
  3 +description: Investigation findings for "运行历史(gc_runs_list)点击跳转错误 + 缺运行详情页" — root cause confirmation and exact reusable pieces, needed for SDD/Benchmark content of this task.
  4 +metadata:
  5 + type: project
  6 +---
  7 +
  8 +Investigated 2026-08-06 for "控制台运行历史点击后跳转错误的 bug,并补上缺失的运行详情页"
  9 +(graph_manifest planned same session). Confirmed by reading the code (not by trusting the task's
  10 +framing):
  11 +
  12 +**Root cause, confirmed exactly as stated**: `mountArtifactsOverviewPanel()`
  13 +(`frontend/app.js:1530-1580`) renders `#gc_runs_list` from the real, working
  14 +`GET /api/work-graph-runs?project_id=` (`work_graph_run_query.list_work_graph_runs`). Row click only
  15 +calls `onSwitchToTask(li.dataset.runTaskId)` → `mountGraphConsole`'s `loadTaskAndRender`, which just
  16 +re-selects that task in `#gc_task_select`. There is genuinely no run-detail route today — the
  17 +existing inline comment at app.js:1524-1529 documents this as a deliberate FR-5 trade-off ("Graph
  18 +run rows are the one exception... since there's no separate 'run detail' route"), not an oversight
  19 +to silently work around.
  20 +
  21 +**What already exists and must be reused, not rebuilt**:
  22 +- `renderGraphVisualizerPanel(run, {enableNodeClick:true})` (app.js:981-1025) + `mountWorkNodeClickExpand`
  23 + (app.js:1053-1062) + `renderLogViewerHtml`/`mountLogViewer` (app.js:1078-1140) is the *entire*
  24 + "node list + per-node live/static log" mechanism already, used today per-task inside
  25 + `mountGraphConsole`. It takes one `run` object shaped `{run_id, org_node, graph_manifest, nodes: [...]}`
  26 + — nothing here is task-scoped internally except how the caller obtains that `run` object. A new
  27 + `#/runs/:run_id` page can call these same functions directly.
  28 +- `mountLogViewer` already implements exactly requirement #2 (live WS tail via `connectLogTailSocket`
  29 + → `/api/ws/work-nodes/:id/log` for non-terminal nodes, falls back to static `GET
  30 + /api/work-nodes/:id/log` on close/terminal status). Do not touch backend log write/push code.
  31 +- Router pattern to copy: hash routes with a dynamic segment already exist for `#/tasks/:task_id`,
  32 + `#/artifacts/:artifact_id`, `#/skills/:skill_id/audit` (app.js:77-106, regex-matched in `render()`,
  33 + not a full path router). `#/runs/:run_id` should follow the exact same `ROUTE_RE` + `render()`
  34 + branch pattern, not a new routing mechanism.
  35 +
  36 +**Backend gap, confirmed real**: no endpoint queries a single `work_graph_run` by `run_id` today.
  37 +`task_query.get_task` (`src/task_query.py:115-171`) builds `work_graph_runs` (each including
  38 +`nodes` via the already-existing private helper `_work_nodes_for_run(conn, run_id)`,
  39 +task_query.py:174-198) but only filtered `WHERE task_id = ?`. The cheapest correct fix: add a
  40 +sibling query function (e.g. in `work_graph_run_query.py`, which already exists and already owns
  41 +the "query work_graph_run across/outside a single task_id" responsibility per its own docstring)
  42 +that does `SELECT run_id, task_id, org_node, graph_manifest, status, started_at, completed_at FROM
  43 +work_graph_run WHERE run_id = ?` and calls the same `_work_nodes_for_run` (may need exporting from
  44 +task_query or duplicating the one query — duplicating a single small query is cheaper than
  45 +cross-module coupling here; Code Agent should pick based on how `_work_nodes_for_run` is
  46 +imported/underscored elsewhere). New route: `GET /api/work-graph-runs/:run_id`, 404 if missing
  47 +(mirrors `_handle_execution_log_get`'s NotFound handling).
  48 +
  49 +**How to apply**: when writing the SDD, scope this as (a) one new backend query fn + one new GET
  50 +route returning `{run_id, task_id, org_node, status, started_at, completed_at, nodes: [...]}`,
  51 +(b) one new hash route `#/runs/:run_id` composing the existing DAG-panel + log-viewer functions
  52 +verbatim, (c) a one-line change to `gc_runs_list`'s click handler
  53 +(`window.location.hash = "#/runs/" + li.dataset.runId` — note: needs `data-run-id` added next to
  54 +the existing `data-run-task-id`, since the run_id itself isn't currently a `data-*` attribute on
  55 +that `<li>`) — do not touch `list_work_graph_runs`/the list rendering itself per the task's explicit
  56 +constraint #4. Also update or remove the now-stale app.js:1524-1529 comment ("since there's no
  57 +separate 'run detail' route") once the route exists, and decide whether `mountGraphConsole`'s
  58 +existing per-task run panels should also link to the same `#/runs/:run_id` page for consistency
  59 +(not required by the task, but worth a one-line decision note either way).
... ...
.claude/agent-memory/validator/MEMORY.md
... ... @@ -3,3 +3,4 @@
3 3 - [deploy_health_check comment resolved + stale-benchmark pattern](project_deploy_health_check_comment_resolved_stale_benchmark.md) — line 24 comment now PASS-verified; a task's benchmark.md can be superseded by that task's own later code_diff/test_report
4 4 - [Fake-DOM escapeHtml harness gotcha](feedback_fake_dom_escapehtml_harness.md) — ad hoc app.js DOM harnesses need real textContent->innerHTML escaping or escapeHtml() falsely looks blank
5 5 - [Known pre-existing supervisor test failure](project_known_preexisting_supervisor_failure.md) — RollbackPathBFailureTest fails deterministically, unrelated to src/ diffs; confirmed via pre-image checkout
  6 +- [Thin test_report placeholder, solid diff](project_thin_test_report_placeholder.md) — task 837fc183 test_report.md was just a launch stub; code_diff was solid, verified independently anyway
... ...
.claude/agent-memory/validator/project_thin_test_report_placeholder.md 0 → 100644
  1 +---
  2 +name: project-thin-test-report-placeholder
  3 +description: A task's test_report.md artifact can be a near-empty "workflow launched in background" placeholder even when the code_diff is real and solid -- don't treat placeholder test_report content as a signal to distrust the diff.
  4 +metadata:
  5 + type: project
  6 +---
  7 +
  8 +Task 837fc183-f87f-41d9-8bc9-6262d7172834 (Org Graph 三节点条点击可达详情 fix,
  9 +verified 2026-08-06) had a `test_report.md` artifact whose entire content was:
  10 +"Launched the ... workflow ... in the background ... I'll be notified when it
  11 +completes; no further action needed right now." -- i.e. a stub, not an actual
  12 +test report (no assertions listed, no pass/fail summary).
  13 +
  14 +**Why:** despite the thin test_report, the actual `code_diff.patch` was
  15 +complete, well-commented, correctly wired (routing regex, click handlers,
  16 +history.replaceState, deep-link auto-focus, `getLatestRunForOrgNode`
  17 +ascending-array-last-wins logic matching `task_query.py`'s `ORDER BY
  18 +started_at` ASC), and came with its own new smoke test
  19 +(`frontend/test_org_click_through_smoke.js`, 23 assertions, 0 exit code) that
  20 +actually ran clean. Independent verification (reading the full diff, running
  21 +`node frontend/test_*_smoke.js`, running `python3 -m unittest discover -s
  22 +src`, tracing backend `ORDER BY`/API-shape assumptions) found no defects.
  23 +
  24 +**How to apply:** a thin/placeholder test_report.md is not itself grounds for
  25 +FAIL or INCONCLUSIVE -- keep verifying independently via the real code_diff,
  26 +run whatever tests exist, and judge on that evidence. It's worth noting as a
  27 +pipeline/process observation (parallel to [[project_zero_diff_terminal_state_gap]]-style
  28 +gaps), not as a substantive defect, unless independent verification actually
  29 +turns up a problem.
... ...