Commit 8646516eae0cde505e197a7e6470822dcafadf7d
1 parent
bd13bd26
graphlemon: auto-commit uncommitted changes for 90c6ca9d-21eb-4678-ab12-2e2f5bd0…
…11fd-main-checkout-drift
Showing
4 changed files
with
90 additions
and
0 deletions
.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. | ... | ... |