[Artifacts] Implement resolve_embeds() engine — replace {{artifact:ID}} markers with rendered HTML previews done coding:8 reasoning:7

← Artifacts
## REOPENED TASK — CRITICAL CONTEXT This task was previously marked 'done' but the audit could not verify the work actually landed on main. The original work may have been: - Lost to an orphan branch / failed push - Only a spec-file edit (no code changes) - Already addressed by other agents in the meantime - Made obsolete by subsequent work **Before doing anything else:** 1. **Re-evaluate the task in light of CURRENT main state.** Read the spec and the relevant files on origin/main NOW. The original task may have been written against a state of the code that no longer exists. 2. **Verify the task still advances SciDEX's aims.** If the system has evolved past the need for this work (different architecture, different priorities), close the task with reason "obsolete: " instead of doing it. 3. **Check if it's already done.** Run `git log --grep=''` and read the related commits. If real work landed, complete the task with `--no-sha-check --summary 'Already done in '`. 4. **Make sure your changes don't regress recent functionality.** Many agents have been working on this codebase. Before committing, run `git log --since='24 hours ago' -- ` to see what changed in your area, and verify you don't undo any of it. 5. **Stay scoped.** Only do what this specific task asks for. Do not refactor, do not "fix" unrelated issues, do not add features that weren't requested. Scope creep at this point is regression risk. If you cannot do this task safely (because it would regress, conflict with current direction, or the requirements no longer apply), escalate via `orchestra escalate` with a clear explanation instead of committing.

Completion Notes

Auto-completed by supervisor after successful deploy to main

Git Commits (2)

[Artifacts] Implement resolve_embeds() engine for {{artifact:ID}} markers [task:ffb99f3d-6ab5-4efe-be3c-9d33714b5da1]2026-04-13
[Artifacts] Implement resolve_embeds() engine for {{artifact:ID}} markers [task:ffb99f3d-6ab5-4efe-be3c-9d33714b5da1]2026-04-03
Spec File

Goal

Implement a resolve_embeds() function that replaces {{artifact:ID}} markers in analysis reports and hypothesis descriptions with rich, interactive HTML previews of artifacts (notebooks, 3D protein structures, pathway diagrams, etc.).

Context

Quest 17 (Rich Artifacts) is highest priority. Analyses and hypotheses can reference artifacts (Jupyter notebooks, protein structures, pathway diagrams), but currently these are just links. We need inline rendered previews for better user experience.

Current State

  • Artifacts exist in artifacts table with types: notebook, protein_structure, pathway_diagram, etc.
  • Analysis reports and hypothesis descriptions contain markdown text
  • No inline preview system exists in post_process.py
  • api.py already has a sophisticated _resolve_embeds / _render_artifact_embed_html for API endpoints, but post_process.py (which generates HTML reports via generate_report()) has no such function

Implementation

1. Create resolve_embeds() function

Location: post_process.py (before the Quality Gates section)

_EMBED_PATTERN = re.compile(r'\{\{artifact:([a-zA-Z0-9_-]+)\}\}')

def _render_artifact_embed_html(artifact_id: str, db) -> str:
    """Render HTML for one artifact embed marker."""
    # Queries artifacts table, returns typed HTML for each artifact type
    ...

def resolve_embeds(text: str) -> str:
    """Replace all {{artifact:ID}} markers with rendered HTML previews."""
    if not text:
        return text
    db = get_db()
    try:
        def replace_embed(match):
            artifact_id = match.group(1).strip()
            return _render_artifact_embed_html(artifact_id, db)
        result = _EMBED_PATTERN.sub(replace_embed, text)
    finally:
        db.close()
    return result

2. Supported Artifact Types

  • hypothesis: Rich hypothesis card with score badge and link
  • figure: SVG inline or image with caption
  • protein_design: Protein design card with mutations, stability, binding affinity
  • model: Model card with framework, parameters, metrics
  • tabular_dataset / dataset: Data table preview (first 10 rows) or source card
  • notebook: Notebook card with link to full view
  • generic fallback: Generic artifact card for unknown types

3. Integration in generate_report()

In the hypothesis description handling within generate_report():

desc_full = html_unescape.unescape(h[3])
# Resolve artifact embeds if description contains markers; otherwise truncate
if "{{artifact:" in desc_full:
    desc_html = resolve_embeds(desc_full)
else:
    desc_html = desc_full[:200] + ("..." if len(desc_full) > 200 else "")

This preserves existing behavior (200-char truncation) for descriptions without artifact markers, and renders full descriptions with embedded artifacts when markers are present.

Acceptance Criteria

resolve_embeds() function implemented in post_process.py
_render_artifact_embed_html() handles all key artifact types
☑ Integrated into generate_report() — artifact markers in hypothesis descriptions trigger full rendering
☑ Missing/invalid artifact IDs return safe error placeholder (not crash)
☑ Python syntax validated (python3 -m py_compile post_process.py passes)
☐ Tested with real artifact markers in production data

Dependencies

  • Artifacts table exists with artifact IDs and types
  • get_db_write() from database module available in post_process.py

Dependents

  • Quest 16 (Demo Showcase) — needs rich artifacts for impressive demos
  • Other artifact-related tasks in Quest 17

Work Log

2026-04-03 - Original attempt (orphan commit fe6e3e7f0)

  • Implemented resolve_embeds() in post_process.py
  • Integrated into generate_report()
  • Commit was never merged to main (ORPHAN_BRANCH)

2026-04-13 - Current implementation

Context: Commit fe6e3e7f0 existed in many branches but NOT in origin/main. Re-implementing on current main.

Changes:

  • Added _EMBED_PATTERN regex and _render_artifact_embed_html() function to post_process.py (~130 lines), placed before the "Quality Gates" section at line 588
  • Supports artifact types: hypothesis, figure, protein_design, model, tabular_dataset, dataset, notebook, generic fallback
  • Added resolve_embeds() function that uses get_db() to look up artifacts and substitute HTML
  • Modified generate_report() (line ~2293) to check for {{artifact: markers and call resolve_embeds() when present, preserving truncation for non-artifact descriptions
  • Fixed Python syntax error in nested f-string (dataset embed section)
  • Verification:

    • python3 -m py_compile post_process.py — ✅ passes
    Next Steps:
    • Add /artifacts/{id}/preview endpoint to api.py for notebook rendering
    • Test with real artifact markers in production data

    Payload JSON
    {
      "requirements": {
        "coding": 8,
        "reasoning": 7
      },
      "completion_shas": [
        "84e32e5a5e412fdae6fc38d0f1981c0139be017f",
        "fe6e3e7f0934f33ee4b6be391888ce2bf67a8117"
      ],
      "completion_shas_checked_at": "2026-04-14T00:41:31.569373+00:00"
    }

    Sibling Tasks in Quest (Artifacts) ↗