Skip to content

feat: shareable task-page deep links in commits and reviews#77

Open
fshehadeh-sfl wants to merge 9 commits into
mainfrom
feat/task-page-links
Open

feat: shareable task-page deep links in commits and reviews#77
fshehadeh-sfl wants to merge 9 commits into
mainfrom
feat/task-page-links

Conversation

@fshehadeh-sfl

@fshehadeh-sfl fshehadeh-sfl commented Jun 29, 2026

Copy link
Copy Markdown
Collaborator

Summary

Each task now has its own dedicated, shareable page in the admin UI, and every artifact Virtual Engineer produces links back to it — so a human reading a commit or a review can navigate straight to the VE page showing what was done for that task.

What's included

  • Deep-linkable task pages — the admin SPA now uses hash routing (#/tasks/<id>) with browser back/forward support. The selected task is driven by the URL, and TaskDetail gains a copy-link button that yields a shareable URL.
  • Commit trailers — agent commits get a deterministic, idempotent Virtual-Engineer: <url> footer (alongside Change-Id), injected in the agent-worker so it applies across Gerrit, GitLab, and GitHub.
  • Review summaries — posted review summaries/votes append a — Reviewed by Virtual Engineer: <url> line back to the task page.
  • PUBLIC_BASE_URL config — new optional env var for the public base URL used to build shareable links. When unset, task-page links are simply omitted from commit trailers and review summaries (we never emit a non-shareable localhost URL into artifacts that leave the machine). The value is shared by the orchestrator, review orchestrator, and dashboard bootstrap; the dashboard's copy-link button additionally falls back to the current browser location client-side.

Notes

  • The commit-trailer change runs inside the agent container, so the agent image must be rebuilt for it to take effect at runtime:
    docker build -f Dockerfile.agent -t virtual-engineer-workspace:latest .

Validation

All gates green on branch HEAD:

  • npm run typecheck / npm run typecheck:ui — zero errors
  • npm run lint — clean
  • npm run build:ui — builds
  • npm test — 1621 passed

fshehadeh-sfl and others added 5 commits June 29, 2026 16:04
Introduce an optional PUBLIC_BASE_URL setting (blank-string-safe,
validated as a URL) plus buildTaskPageUrl / resolvePublicBaseUrl
helpers. These produce shareable hash-routed deep links of the form
<base>/#/tasks/<id> used by later commits to link commits and
review summaries back to a task's admin page.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Thread the resolved task-page URL from OrchestratorConfig through the
agent session and into the container as VE_TASK_PAGE_URL. The
agent-worker now appends a deterministic `Virtual-Engineer: <url>`
footer alongside the Change-Id when rewriting agent commits, so every
commit VE produces links back to its task page.

The trailer injection is idempotent and provider-agnostic (Gerrit,
GitLab, GitHub), reusing the existing rebase-based footer rewrite.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Append a `— Reviewed by Virtual Engineer: <url>` line to the posted
review summary (and vote message) when a public base URL is
configured. The raw summary is preserved for the persisted cycle
record; only the posted copy carries the link, and it is added
idempotently.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add hash-based routing to the admin SPA so each task is reachable at
`#/tasks/<id>` (with browser back/forward support). The selected task
is now driven by the URL, and TaskDetail gains a copy-link button that
yields a shareable URL, preferring the configured public base URL and
falling back to the current origin. The public base URL is surfaced to
the client via the dashboard bootstrap.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Resolve the public base URL once in the composition root and pass it
into the orchestrator config, review orchestrator deps, and admin
runtime config so commit trailers, review summaries, and the dashboard
bootstrap all share the same resolved value.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds shareable, deep-linkable task pages to the admin UI and propagates those links into the artifacts Virtual Engineer generates (agent commits and review summaries), backed by a new PUBLIC_BASE_URL config used to build stable external URLs.

Changes:

  • Introduces hash-based routing for the admin SPA (#/tasks/<id>) plus a copy-link control on the task detail page.
  • Adds a shared URL builder/resolver (buildTaskPageUrl, resolvePublicBaseUrl) and threads the resulting task-page URL through orchestrator/review flows.
  • Injects deterministic commit-message trailers in the agent-worker (Virtual-Engineer: <url> alongside Change-Id) and appends task links to posted review summaries.

Reviewed changes

Copilot reviewed 22 out of 22 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
tests/unit/taskPageUrl.test.ts Adds unit tests for task-page URL building and base-URL resolution.
tests/unit/reviewOrchestrator.test.ts Adds coverage around appending task-page links to review summaries/votes.
tests/unit/orchestrator.test.ts Updates orchestrator test config to include publicBaseUrl.
tests/unit/orchestrator.projectMode.test.ts Updates project-mode orchestrator test config to include publicBaseUrl.
tests/unit/orchestrator.concurrency.test.ts Updates concurrency orchestrator test config to include publicBaseUrl.
tests/unit/dashboard.test.ts Ensures dashboard bootstrap JSON includes publicBaseUrl.
tests/unit/copilotAdapter.test.ts Verifies VE_TASK_PAGE_URL env injection into the agent container.
src/utils/taskPageUrl.ts New helper functions for building task deep links and resolving the external base URL.
src/review/reviewOrchestrator.ts Appends a task-page link to posted review summaries when configured.
src/orchestrator/orchestrator.ts Threads task-page URL into the agent session so the worker can inject commit trailers.
src/interfaces.ts Extends AgentSession with taskPageUrl.
src/index.ts Resolves and wires publicBaseUrl into orchestrator, review orchestrator, and admin bootstrap.
src/config.ts Adds PUBLIC_BASE_URL env var and schema validation.
src/agents/copilotAdapter.ts Passes VE_TASK_PAGE_URL into the agent container env when present.
src/admin/ui/views/TasksView/TaskDetail.tsx Adds “copy shareable link” UI and URL construction logic for task detail.
src/admin/ui/views/TasksView/index.tsx Refactors task selection to be URL-driven (selectedId/onSelect props).
src/admin/ui/types.ts Adds publicBaseUrl to the admin bootstrap typing.
src/admin/ui/App.tsx Implements hash-route parsing/serialization and back/forward sync.
src/admin/dashboard.ts Includes publicBaseUrl in the escaped bootstrap JSON.
src/admin/adminServer.ts Passes publicBaseUrl into the dashboard renderer.
agent-worker/index.js Injects deterministic Virtual-Engineer: (and Change-Id) trailers into agent commits.
.github/copilot-instructions.md Documents PUBLIC_BASE_URL in the env table.

Comment thread src/admin/ui/App.tsx
Comment thread src/admin/ui/views/TasksView/TaskDetail.tsx
Comment thread tests/unit/reviewOrchestrator.test.ts
Comment thread agent-worker/index.js
Comment thread src/orchestrator/orchestrator.ts Outdated
- App.tsx: guard parseHash decodeURIComponent against malformed hashes
- TaskDetail: add type=button + aria-label to copy-link button
- agent-worker: appendCommitTrailer rewrites trailer when value differs
- orchestrator: reject blank publicBaseUrl when injecting taskPageUrl
- tests: cover appendCommitTrailer converge/no-op behavior
@fshehadeh-sfl

Copy link
Copy Markdown
Collaborator Author

Addressed the Copilot review in cf03b2a:

  1. src/admin/ui/App.tsxparseHash now decodes the task id via a safeDecode helper (try/catch), so a malformed hash like #/tasks/%E0 no longer throws URIError and crashes the SPA on load/hashchange.
  2. src/admin/ui/views/TasksView/TaskDetail.tsx — the copy-link icon button gains type="button" and an aria-label (in addition to title) for a reliable accessible name.
  3. agent-worker/index.jsappendCommitTrailer now converges to the desired value: it leaves the line untouched when the value matches and rewrites it in place when it differs (e.g. after PUBLIC_BASE_URL changes). A replacer function is used so $ in the value isn't treated as a replacement pattern. Change-Id continuity is preserved because that caller only invokes it when no Change-Id exists.
  4. src/orchestrator/orchestrator.ts — the taskPageUrl injection guard now also rejects blank/whitespace publicBaseUrl, matching appendReviewTaskLink.
  5. reviewOrchestrator.test.ts "no link when base URL omitted" — left as-is: it exercises the real appendReviewTaskLink blank-guard (a legitimate defensive code path); the happy-path link is already covered by the preceding test.

Added appendCommitTrailer regression tests (append / group / no-op / rewrite-on-differing-value / $-safety) in tests/unit/workerCommitProtocol.test.ts.

Gates green: typecheck, typecheck:ui, lint, build:ui, npm test (1626 passed).

Note: the trailer change runs inside the agent container — rebuild the agent image to pick it up at runtime: docker build -f Dockerfile.agent -t virtual-engineer-workspace:latest .

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 23 out of 23 changed files in this pull request and generated 4 comments.

Comment thread src/admin/ui/views/TasksView/index.tsx
Comment thread src/index.ts Outdated
Comment thread src/index.ts Outdated
Comment thread agent-worker/index.js
Addresses second Copilot review on PR #77:

- TasksView: a non-null deep-link id that is not in the loaded task list
  now shows a 'not found' state instead of silently rendering the first
  task (preserves the #/tasks/<id> deep-link contract).
- index.ts: stop falling back to http://<host>:<port> for commit trailers
  and review summaries; only embed task-page links when PUBLIC_BASE_URL is
  explicitly configured. Avoids leaking non-shareable localhost links into
  artifacts that leave the machine. Removes now-unused resolvePublicBaseUrl.
- agent-worker: rename injectChangeIds -> injectCommitTrailers to reflect
  that it injects both Change-Id and Virtual-Engineer trailers.
- docs: config comment + copilot-instructions env note updated.
@fshehadeh-sfl

Copy link
Copy Markdown
Collaborator Author

Thanks for the second pass @copilot — addressed in c45aad1:

  • TasksView deep-link: a #/tasks/<id> link pointing at a task that isn't in the loaded list now renders an explicit "Task … was not found" state instead of silently falling back to the first task (guarded against the initial-load flash).
  • localhost fallback for task links (index.ts review + orchestrator paths): we no longer fall back to http://<host>:<port>. Task-page links are embedded in commit trailers / review summaries only when PUBLIC_BASE_URL is explicitly set, so we don't leak non-shareable localhost URLs into artifacts that leave the machine. The now-unused resolvePublicBaseUrl helper (and its tests) were removed.
  • agent-worker: renamed injectChangeIdsinjectCommitTrailers to reflect that it injects both Change-Id and Virtual-Engineer trailers.
  • Docs (config comment + copilot-instructions env note) updated to match.

Gates green: typecheck, typecheck:ui, lint, build:ui, and npm test (1623 passing).

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 23 out of 23 changed files in this pull request and generated 3 comments.

Comment thread agent-worker/index.js
Comment thread src/index.ts
Comment thread src/admin/ui/views/TasksView/TaskDetail.tsx
- agent-worker: detect the Virtual-Engineer trailer by parsing the
  trailer key/value instead of substring-matching the body, so a URL
  that only appears in free text no longer yields a false 'already
  present' (skipping injection) and a stale trailer value is reliably
  converged. Adds regression tests for the pre-check.
- TaskDetail: drive the 'link copied' reset from a useEffect with
  cleanup so the timer is cancelled on unmount / re-copy, avoiding a
  setState-on-unmounted-component warning.
@fshehadeh-sfl

Copy link
Copy Markdown
Collaborator Author

Thanks for the third pass @copilot — addressed in e25a157 (+ PR description update):

  • agent-worker needsVeTrailer (comment on injectCommitTrailers): the pre-check now parses the ^Virtual-Engineer: trailer key/value instead of substring-matching the body. A URL that appears only in free text no longer yields a false "already present" (which previously skipped injection), and a stale trailer value is reliably converged. Added regression tests in workerCommitProtocol.test.ts for the "URL present in free text but trailer missing", stale-value, missing-in-set, and no-URL cases.
  • TaskDetail copy-link timeout: the "copied" reset is now driven by a useEffect with cleanup (clearTimeout), so the timer is cancelled on unmount / re-copy — no more potential setState-on-unmounted warning.
  • PR description vs. implementation: updated the PUBLIC_BASE_URL bullet to match the implemented behavior — links are omitted when the var is unset (no localhost fallback); the dashboard copy-link button keeps its client-side window.location fallback.

Gates green: typecheck, typecheck:ui, lint, build:ui, and npm test (1628 passing).

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 23 out of 23 changed files in this pull request and generated 3 comments.

Comment thread src/admin/ui/views/TasksView/TaskDetail.tsx
Comment thread .github/copilot-instructions.md
Comment thread agent-worker/index.js
- TaskDetail: clear stale actionError when copying the task link so a
  prior failure message no longer lingers after a successful copy.
- agent-worker: escape regex metacharacters in appendCommitTrailer's
  trailer key before building the RegExp (defensive); add regression test.
- docs: sync admin.md (task hash-routing + copy-link) and testing.md
  (taskPageUrl spec) per the doc auto-sync rules.
@fshehadeh-sfl

Copy link
Copy Markdown
Collaborator Author

Thanks for the fourth pass @copilot — addressed in 6d9f7e1:

  • TaskDetail stale error (comment on copyTaskLink): the function now calls setActionError(null) on entry, so a prior failure message no longer lingers and make a successful copy look like it failed.
  • appendCommitTrailer unescaped key: the trailer key is now escaped (key.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")) before building the RegExp, so a key containing regex metacharacters can never cause an incorrect match/replacement or a runtime error. Current keys are static literals, so this is defensive; added a regression test (escapes regex metacharacters in the trailer key).
  • Doc auto-sync: updated .github/context/modules/admin.md (Tasks view hash routing #/tasks/<id> + Task detail copy-link button) and .github/context/testing.md (added taskPageUrl to the spec inventory) in the same commit.

Gates green: typecheck, typecheck:ui, lint, build:ui, and npm test (1629 passing).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants