spec render lens · flow-next · post-plan · 2026-06-12

fn-62 Optional HTML artifact mode: spec & PR render lenses

spec & PR review surfaces as self-contained HTML — opt-in, regenerable, markdown stays the record · tracker FLOW-12 · repo gmickel/flow-next
openstatus · plan ship
14r-ids
14 / 14r-id coverage
8tasks · 2 done · 1 active
7critical-path depth
opt-inactivation · off default
2.0.0release vehicle
01

Thesis

scope: business

flow-next's human touchpoints — spec review, plan review, diff review — are markdown-only today. This feature adds an optional HTML artifact mode: when activated via setup/config, the lifecycle skills load one progressively disclosed reference file and emit self-contained, beautifully rendered HTML lenses beside their markdown output — maximum legibility and review ergonomics for POs, PMs, and devs, while markdown-only users see zero change.

The load-bearing clarification: markdown (and tracker-sync) stays 100% the source of truth. Every HTML output is a regenerable render lens, never the record — one-way derivation, never parsed back as state. Validated by smoke test on real history (fn-52 spec visualizer, PR #171 review instrument) before this spec was written.
02

Task graph

8 nodes · hover a node to light its r-ids below
L0
fn-62.1
Config gate + .flow/artifacts layout + setup ceremony (lavish offer)
done
L1
fn-62.2
Shared disclosure reference (design system + generation rules) + Codex mirror
done
L2
fn-62.3
Spec-lens integration: capture + plan touchpoints, lavish session, state-dependent rendering
in progress
fn-62.4
PR-lens integration: make-pr emission, R-ID verification, link strategy
todo
L3
fn-62.5
Repo docs: html-artifacts doc + README/teams/ralph/GLOSSARY/CLAUDE.md surfaces
todo
L4
fn-62.7
flow-next.dev feature pass: visual-aids pages, landing card, both navbars, changelog
todo
L5
fn-62.8
flow-next.dev strategy/pipeline pass: pipeline page, autonomy content, Introduction
todo
L6
fn-62.6
2.0.0 release: bump, crossEpic alias removal, Codex mirror regen + audit, CHANGELOG
todo
critical path · .1 → .2 → .3 → .5 → .7 → .8 → .6 (7 deep) dependency parallel lane: .4 (PR lens) runs beside .3 off the shared .2 base
03

Acceptance criteria

14 rows · provenance-tagged · scope: both
R-IDCriterionProvenanceOwned by
R1HTML mode is opt-in via setup/config, OFF by default. Off ⇒ no reference load, no artifacts, no Lavish sessions, no behavior-visible output — the heavy disclosure file costs zero tokens.userparaphrasefn-62.1
R2When active, skills load a progressively disclosed shared reference file: generation rules + explicit anti-slop design system (own typography/palette; no CDN fonts; no purple-gradient defaults).userparaphrasefn-62.2
R3Markdown + tracker-sync remain the sole source of truth; every HTML output is an additional regenerable artifact, never parsed back as state.userfn-62.2fn-62.3
R4Spec artifact uses ONE generation pathway with state-dependent rendering: spec-only before tasks exist; spec+plan layer (task DAG, R-ID coverage matrix) once tasks exist.userparaphrasefn-62.3
R5PR artifact is diff-derived (never commit messages), verified against the spec's R-ID export before publishing; read-only review instrument.userparaphrasefn-62.4
R6All artifacts are self-contained single-file HTML — inline CSS/JS, zero external requests, print-friendly.paraphrasefn-62.2
R7Lavish (lavish-axi) ships as an optional dependency: detect-on-PATH, never required; when present + interactive, spec/plan artifacts open as sessions and annotations map to markdown-source edits + lens regeneration.userfn-62.2fn-62.3
R8The PR artifact never enters the annotate-edit loop; autonomous/Ralph contexts never run a Lavish poll.userparaphrasefn-62.3fn-62.4
R9The setup ceremony, on HTML opt-in, documents and offers the lavish-axi install — including the session-spanning feedback model and idle-stop/resume behavior.userfn-62.1
R10Markdown spec and make-pr output link to their HTML artifacts; the GitHub display limitation is documented with local-open guidance.userfn-62.3fn-62.4fn-62.5
R11Artifacts live in a dedicated regenerable location under .flow/, commit-or-gitignore per project.inferredfn-62.1
R12flow-next.dev surfaces this as a mainline feature: landing page, SPECS/TEAMS/REVIEW sections, a new visual-aids page (both navbars), changelog entry, build gate green.userfn-62.7
R13flow-next.dev strategy/pipeline pass in the same workstream: a pipeline page, the missing autonomy-suite content, Introduction narrative updated to match.userfn-62.8
R14Released as 2.0.0 — repo docs, Codex mirror regen, manifest/version lockstep, CHANGELOG.userfn-62.5fn-62.6
04

Architecture

scope: technical

Activation gate

flowctl config get artifacts.html.enabled — written by the setup ceremony, OFF by default. Off ⇒ skills load nothing extra: zero token cost, zero behavior change. The one flowctl edit is the artifacts default block in get_default_config; everything else is skill prose.

↓ when enabled, participating skills load ↓

Shared disclosure reference

plugins/flow-next/references/html-artifacts.md — design system (instrument-panel house style), generation rules, per-lens guidance, DAG discipline, Lavish protocol, pre-publish checklist. ONE generator definition; tool-name-agnostic so the Codex mirror needs no rewrite pass.

↓ consumed at three lifecycle touchpoints ↓

capture → spec lens

Phase 5 post-write emits .flow/artifacts/<spec-id>/spec.html — pre-plan, spec-only business-review view.

plan → spec lens

After Step 8's refinement loop exits, the SAME pathway regenerates at the SAME path — now with the task DAG, coverage matrix, critical path.

make-pr → PR lens

Emits pr.html from git diff --stat + the R-ID export; injects the body link before gh pr create. Read-only — no annotate loop, ever.

↓ optional companion — detect, never require ↓
1detect

command -v lavish-axi — absent ⇒ plain artifact, zero mention, never an error.

2open (interactive only)

lavish-axi <abs-path> opens an annotation session keyed on the absolute artifact path.

3pull-only feedback

Annotations queue in ~/.lavish-axi/state.json — session-spanning, survives agent death; any later session drains via lavish-axi poll.

4apply + regen

Each annotation maps to an edit of the markdown source of truth, then the lens regenerates at the fixed path.

05

Edge cases & constraints

grouped by blast radius

Contract integrity — break these and the model collapses

  • Stale-lens risk: artifacts regenerate at lifecycle touchpoints and are never parsed back as state; every footer carries a staleness stamp (spec updated_at + commit at render time).
  • R-ID mismatch (PR lens): diff vs R-ID-export disagreement renders as a visibly flagged row — warn-in-artifact, never block make-pr.
  • Self-contained or nothing: zero external requests, fonts included — must open identically from disk, in Lavish, in CI archives, printed.

Workflow discipline — make-pr & plan side effects

  • make-pr: --dry-run writes NO artifact; committed-mode stages ONLY pr.html (never git add -A) as chore(flow): pr artifact <spec-id>; generation failure is non-fatal; Ralph's PR_URL= stdout contract untouched.
  • Link idempotency: the spec's artifact-link line is replaced in place on every regen — never duplicated.
  • Plan timing: the lens generates AFTER Step 8's refinement loop exits, never mid-edit.

Environment realities — GitHub, paths, storage

  • GitHub can't render committed HTML and rejects .html attachments — bodies link with local-open guidance; no hosting over-engineering.
  • Fixed deterministic paths: spec.html / pr.html, never timestamped — Lavish keys sessions on the absolute path. Worktree caveat documented and accepted.
  • Link strategy follows ignore status: committed by default (blob links resolve); gitignored projects get local-open guidance only — never a 404 blob link.
  • localStorage is try-wrapped progressive enhancement; artifacts stay fully readable without it.

Graceful degradation — absence is invisible

  • No lavish on PATH ⇒ plain artifact, zero mention. Server idle-stop ⇒ still a static page; reopening resumes.
  • Autonomous discipline: pilot/Ralph generate artifacts but never open sessions, never poll — at most a one-line pending-prompts note.
  • DAG discipline: layered CSS grid + DOM-measured edges — hand-typed SVG coordinates banned; >~20 nodes collapse to lanes.
06

Boundaries

scope: business

This IS

  • Fully opt-in — markdown-only users see zero new steps, prerequisites, or token overhead (zero-dep base contract preserved).
  • Regenerable render lenses beside markdown output — spec lens (one state-dependent pathway) + read-only PR lens.
  • Lavish as detect-on-PATH optional dep — same shape as clawpatch / /flow-next:map.
  • Committed by default under .flow/artifacts/, gitignore offered at setup.
  • A 2.0.0 mainline feature, surfaced on flow-next.dev.

This is NOT

  • A storage format — no state ever lives in artifacts.
  • A Lavish wrapper or bundle — never wrapped, bundled, or required.
  • PR-annotation → review-comment plumbing — explicitly out of scope (plausible future increment).
  • Review-report artifacts (impl-review / plan-review / qa as HTML) — later increment.
  • The codex-apop delegation hardening — deliberately deferred behind this ("bigger bang for our buck").
07

Decision context

capture + planning decisions
D1

Lavish: detect, don't wrap

Its portable-artifacts guarantee means plain self-contained HTML gets the annotate loop for free when present. Pull-only architecture (CLI long-poll, global state file, no MCP) keeps coupling at zero and makes feedback session-spanning.

"the lavish editor is definitely a large boon … lavish is a go as an optional dep"

Rejected: wrapping/bundling — adds a Node dependency to the zero-dep base for no gain.

D2

One artifact pathway, not two

Spec-vs-plan is a rendering question (what state exists), not a product question. Same generator, same path, same flowctl export.

"i think it would be the same pathway, we would just generate the html using information from the spec and/or the spec + tasks"

Rejected: separate spec/plan artifact types — a needless config axis.

D3

Annotate loop scoped to spec/plan only

A PR artifact derives from an immutable diff, and GitHub already owns review comments — duplicating that surface creates a sync problem.

"the agentic editing of a PR doesnt make sense does it?"

Rejected: PR-lens annotate loop.

D4

No new slash command

Auto-regen rides the existing lifecycle skills (capture, plan, make-pr); ad-hoc regeneration is conversational — the host agent reads the disclosure file on request. Skill surface stays flat per repo rule; interview integration is OUT of v1.

Rejected: a dedicated artifact skill / fourth wiring point.

D5

No deterministic Python renderer

Generation is the host agent reading the disclosure file (the repo's agentic-vs-deterministic rule); flowctl's only contribution is the config default block.

Rejected: a flowctl HTML generator — brittle, unmaintainable, worse output.

D6

Release task runs last

The 2.0.0 release (fn-62.6) depends on the flow-next.dev tasks because the release procedure needs the docs-site changelog + version bump before the tag: order .5 → .7 → .8 → .6. The planSync.crossEpic alias removal rides the release task as its own breaking-change CHANGELOG line — kept visible, not folded silently into the bump.

08

Early proof point

the core bet — and this page is the experiment

Task fn-62.2 (the disclosure reference) validated through fn-62.3's first real regeneration: a fresh agent session reading ONLY the disclosure file must reproduce the smoke-test house style — instrument-panel design, layered DAG, source-tag chips, staleness stamp, zero external requests — for fn-62 itself, matching the hand-built artifacts in ~/Documents/flow-next-artifact-smoke/ without having seen them.

If the output drifts sloppy or inconsistent, fix the reference file's rules/examples/checklist BEFORE building the PR lens (fn-62.4) and docs (fn-62.5+).