name: project-artifact-overview-click-through-bug description: "RESOLVED 2026-08-06 (re-verified by direct file read): all 3 gaps fixed — data-artifact-id, #/artifacts/:id route, and mountArtifactBrowser(initialArtifactId) all present." metadata:
type: project
RESOLVED as of 2026-08-06 (re-verified by reading frontend/app.js directly while
investigating the unrelated Org Graph click-through bug, see [[project-org-strip-click-through-bug]]):
all three gaps below have been fixed. renderArtifactSummaryList/renderArtifactSummaryList's
<li> now carries data-artifact-id (app.js:1360), ARTIFACT_DETAIL_RE (#/artifacts/:id) is a
real dynamic route wired in render() (app.js:99,125-129), and mountArtifactBrowser(initialArtifactId)
(app.js:1603) seeds selectedArtifactId from it and calls the existing showPreview() flow. Don't
re-flag this as open without re-reading the file first — but do keep re-verifying, per CLAUDE.md's
general warning that autonomous self-hosting runs can fix or re-break things between sessions.
Original investigation (2026-08-04), kept for history — root cause was real and narrower than it first looked, three separate gaps, not one:
renderArtifactSummaryList()(frontend/app.js:1344) renders bare<li>with nodata-artifact-idand no click handler — confirmed, matches the task's stated root cause.- The router (
frontend/app.js:77-132,routesobject +render()) does exact-string lookup onwindow.location.hash(routes[hash]), with only two regex-based dynamic routes today:TASK_DETAIL_RE(#/tasks/:id) andSKILL_AUDIT_RE(#/skills/:id/audit). There is no query-string parsing anywhere in the router — a hash like#/artifacts?artifact_id=xxxwould failroutes[hash]and both regexes and fall through to "Not found". Fixing this bug requires extending routing (either a new#/artifacts/:id-style dynamic route matched the same way asTASK_DETAIL_RE, or adding query-string stripping/parsing torender()before route lookup) — it is not just a matter of adding anhref. mountArtifactBrowser()(frontend/app.js:1582) already has the exact mechanism needed to display a specific artifact once you have its id —showPreview(artifactId)setsselectedArtifactIdand fetches/api/artifacts/:id— but it is only ever invoked from a click onli[data-artifact-id]insiderefreshList(), never from a URL param. The comment at app.js:1353-1356 ("v_artifact_browser and v_task_board don't parse URL query params today ... out of scope") was written about the "查看全部" link specifically (intentionally unfiltered) — it is not evidence that per-item deep-linking is already supported or was rejected; don't misread it as covering this case.
How to apply: when writing the SDD for this task, the technical design must cover (a)
adding data-artifact-id + click → hash navigation in renderArtifactSummaryList, (b) a
route-level change (new dynamic route or hash query-parsing) so #/artifacts can carry an
artifact id, and (c) mountArtifactBrowser reading that id on mount and calling the
existing showPreview()/refreshList() flow to preselect it — reusing c_artifact_get /
GET /api/artifacts/:artifact_id as-is, no new content-preview logic. The "查看全部" links
(app.js:1387-1390) must keep pointing at plain #/artifacts / #/tasks — do not add the
id param to those.