Skip to content

feat(6.8): role-template management UI — versioning, full + augmented types#39

Merged
fstamatelopoulos merged 8 commits intomainfrom
iteration-6/role-template-management-6.8
May 9, 2026
Merged

feat(6.8): role-template management UI — versioning, full + augmented types#39
fstamatelopoulos merged 8 commits intomainfrom
iteration-6/role-template-management-6.8

Conversation

@fstamatelopoulos
Copy link
Copy Markdown
Owner

Summary

Adds a top-level "Agents" tab to the web UI for managing each agent role's instruction template. Per-role versioning + promote-to-production with two complementary modes:

  • full — body replaces the bundled cf² default. Maximum flexibility (delete sections, restructure); doesn't auto-pick-up cf² upgrades. UI shows a "Forked from cf² vX.Y.Z" badge so users know their version may be drifting.
  • augmented — body is appended to the live bundled default at promote time and every server boot. The bundled default is read live (never duplicated on disk), so when cf² ships a new template, the user's extension automatically rides along on the new version. Upgrade-friendly by default.

Hooks into the existing user-global override path (~/.cfcf/templates/<name> — what getTemplate() already reads) so the runtime is unchanged. Promote writes the (composed-for-augmented) content there; revert-to-default deletes it.

What's new

Core (packages/core/src/role-templates.ts)

  • New module with full CRUD: listManagedTemplates, getManagedTemplate, getVersionContent, saveVersion, updateVersion, deleteVersion, promoteVersion, findOrphanedVersions, refreshAugmentedOverrides.
  • Storage at ~/.cfcf/templates-managed/<name>/{manifest.json, v_<id>.md}. Manifest self-heals on corruption; missing version files fall back gracefully.
  • Round-1 manifests (no type field) read back as type: "full" automatically — no migration needed.
  • getEmbeddedTemplate(name) newly exported from templates.ts for read-only access to the bundled default.

Server

  • New /api/role-templates/* endpoints (list / get / per-version content / create / update / delete / promote) with uniform { error: string } envelope.
  • Boot-time auto-recompose for augmented overrides (refreshAugmentedOverrides() called from start.ts after the orphan reaper). Cheap idempotent pass — only writes when on-disk content actually differs from live composition. Single log line on change. Full versions are not touched (frozen by design).

Web UI

  • New /agents route (Header link between Memory and Settings). Optional ?template=<name> query for deep-linking.
  • Tab strip ordered by natural agent execution sequence: Solution Architect → Developer → Judge → Reflection → Documenter. Tabs whose role currently uses a custom version show a marker.
  • Action bar: Edit (full-edit mode) / Augment (augmented-edit mode) / Promote / Revert to default / Delete version.
  • Two editor layouts: single textarea for full-type versions; split view for augmented (read-only standard on top + editable extension below). Both panels at 25vh floor height with resize: vertical handle.
  • Version selector dropdown shows <label> — <type> (<date>) — promoted for each entry. Bundled default always selectable, never deletable.
  • "Forked from cf² vX.Y.Z" badge below the selector for full versions (since they don't auto-upgrade).
  • Status messages above the version selector with non-directional wording.

Naming + ordering polish (informed by user feedback)

  • Renamed the process.md tab from "Workspace Process" to "Developer" — the file's content literally opens with "You are a dev agent…", so it functionally serves as the dev role's primary instruction template even though the historical filename predates the per-role-instructions convention.
  • Tab order matches the natural agent execution flow within an iteration loop (architect → dev → judge → reflection → documenter).

Documentation

  • New design doc: docs/design/role-template-management.md.
  • Full documentation audit (commit 804824c) — updated 9 user-facing docs to align with this PR + recent changes (items 6.30, 6.31, 6.33). Stale "manually-invoked Solution Architect via cfcf review is interactive" claims removed (verified in code: SA is headless on all paths). New endpoints documented in docs/api/server-api.md. CLAUDE.md gains bullets for role-template management, orphan reaper, ollama auto-refresh, and the architect-always-unattended classification.

Test plan

  • bun run typecheck — clean
  • bun test packages/core packages/cli packages/web — 845/845 pass (41 unit tests in role-templates.test.ts, 17 endpoint tests, 3 route-parser tests)
  • cd packages/web && bun run build — clean
  • Manual — open Agents tab, click around the five roles
  • Manual — Edit on Default → save as new full version → Promote → verify ~/.cfcf/templates/<name> contains the body verbatim
  • Manual — Augment on any role → type extension → save as new augmented version → Promote → verify override file = <bundled default> + separator + <extension>
  • Manual — manually edit the override file to clobber the bundled-default portion → restart server → verify [server] Re-composed N augmented role-template override(s)… log line + override file is back to <fresh bundled> + <extension>
  • Manual — delete a promoted version → verify auto-revert to default + override file deleted

Notes

  • Round 1 (initial full-template editing) and round 2 (augmented type + boot-time recompose) ship together in this PR — there's no intermediate state worth merging separately.
  • Out of scope (deferred follow-ups): dev-role custom-directions block (dev's Tier-1 instructions are programmatically generated by context-assembler.generateInstructionContent(), not file-loaded — needs a different sentinel-merge insertion-point design); Product Architect / Help Assistant system-prompt management (their prompts are programmatically assembled); per-project (workspace-local) override management UI; diff viewer between versions.
  • Pre-existing app.test.ts config-merge failure on main is unrelated to this PR (verified earlier in iter-6 via git stash && bun test).
  • Branch contains 11 commits — the work was iterated with user feedback. A squash-merge will keep main history clean if you'd prefer; happy either way.

fstamatelopoulos and others added 8 commits May 8, 2026 18:43
…uction

New top-level "Agents" tab in the web UI for editing the instruction
templates each agent role reads. Each role gets:
  - A bundled cf² default (always selectable, read-only, never deletable).
  - Any number of saved versions stored under
    `~/.cfcf/templates-managed/<name>/{manifest.json, v_<id>.md}`.
  - A "Promote to production" action that writes the selected version's
    content to `~/.cfcf/templates/<name>` — the existing user-global
    override path that `getTemplate()` already reads. Reverting to default
    deletes the override file so cf² falls back to the embedded template.
    No runtime changes to agent spawning.

Decoupled from the prior "blocked on 6.11/ADLC" framing: the user's
vision (edit + version + promote) operates at per-role-template
granularity — whatever role abstraction ADLC eventually settles on
can layer on top of this without rework.

**Shipped (round 1)**

- `packages/core/src/role-templates.ts` — versioning manager.
  list / get / save / update / delete / promote, manifest self-heal
  on corruption, orphan detection, automatic revert when deleting the
  promoted version, automatic override-file refresh when editing it.
  Bundled defaults sourced via a new `getEmbeddedTemplate(name)`
  exported from `templates.ts`.
- HTTP routes at `/api/role-templates/*` with uniform error envelope.
- Web UI: new `/agents` route (Header link between Memory and Settings),
  tab strip across managed roles, version selector, monospace textarea
  editor, action buttons (Edit / Save as new version / Save changes /
  Promote / Revert / Delete), inline help block. Deep-linkable via
  `/agents?template=<name>`.

**Managed templates (round 1)**: cfcf-architect-instructions.md,
cfcf-judge-instructions.md, cfcf-documenter-instructions.md,
cfcf-reflection-instructions.md, process.md.

**Out of scope (deferred follow-ups)**: dev-role custom-directions
block (Tier-2 from the original 6.8 design — needs the sentinel-merge
insertion-point design first), Product Architect / Help Assistant
system-prompt management (their prompts are programmatically assembled),
per-project override management UI, diff viewer, search-within-content.

**Tests**: 30 unit tests in `role-templates.test.ts` (every flow +
manifest corruption recovery + cross-template isolation), 15 endpoint
tests in `routes/role-templates.test.ts`, 3 new route-parser tests for
the new `/agents` + `?template=` routes. All 834 core+cli+web tests
pass; clean typecheck; web build clean.

Pre-existing `app.test.ts` config-merge failure on main is unrelated
(verified earlier in this iter).

**Design doc**: `docs/design/role-template-management.md`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…indicator

Two small follow-ups on top of 7c67f82:

1. The page only honoured `initialTemplate` on first mount; subsequent
   hash changes (browser back/forward through `?template=...`) were
   silently ignored. Added an effect that syncs activeName when the
   prop changes (and the requested template exists in the loaded
   summary list).

2. When in edit mode with local changes, the page heading now shows
   a yellow "• unsaved changes" indicator. Doesn't replace the
   button-disabled-state cue; just adds a visual signal so the user
   doesn't lose track of dirty state when scrolled away from the
   action buttons.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Brief mention of all five top-level web tabs in the Server / web UI
concept block. Adds discoverability for the new Agents tab without
expanding into a full guide section (the inline help on the page
itself covers the mechanics).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…d version

The previous readOnly gate was `!isEditing || selectionIsDefault` —
so clicking Edit on the bundled-default tab left the textarea
read-only and the user couldn't type at all. The intent was "we
never overwrite the bundled-default file on disk" but the user still
needs to TYPE in the editor to draft a new version that gets saved
via "Save as new version". The save action is what's gated by
selection-is-default (no "Save changes" button on default — only
"Save as new version"); typing should always work in edit mode.

Updated the inline help below the editor to reframe accordingly:
"You're editing a copy of the bundled default. Click Save as new
version to fork your changes into a new version (the cf²-shipped
default itself stays untouched and remains available in the
dropdown)."

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds a second customisation mode alongside round-1's full-template
editing. Each saved version now has a type:

- type="full":      body REPLACES the bundled default at promote time.
                    Maximum flexibility (delete sections, restructure);
                    doesn't auto-pick-up cf² upgrades. UI shows a
                    "Forked from cf² vX.Y.Z" badge so the user knows
                    their version may be drifting.
- type="augmented": body is APPENDED to the live bundled default at
                    promote time AND every server boot. The bundled
                    default is read live (never duplicated on disk),
                    so when cf² ships a new default, the user's
                    extension automatically rides along on the new
                    version. THIS is the upgrade-friendly mode.

Composition lives in `composeForOverride(name, type, body)`:
- "full"      → body verbatim
- "augmented" → getEmbeddedTemplate(name) + AUGMENTATION_SEPARATOR + body

Boot-time auto-recompose: every cfcf server start runs
`refreshAugmentedOverrides()` which, for every managed template whose
promoted version is augmented, re-writes the override file IF the
on-disk content differs from the live composition. Cheap idempotent
pass, single log line on change. Full versions are explicitly NOT
touched (frozen by design — auto-merging would be wrong).

UI changes:
- New "Augment" button next to "Edit" in the action row. Augment
  always creates a new augmented version on top of the bundled
  default (regardless of which version is currently selected).
- Split editor view for augmented versions: bundled default
  rendered read-only at the top (~25vh, smaller for visual emphasis
  on the extension) + extension textarea below (~30vh) with a
  placeholder showing example custom directions. Editing toggles
  only the extension.
- Forked-from-cf²-vX.Y.Z hint below the selector for full versions.
- Version dropdown suffixes each entry with its type.
- "Creating new <type> version" indicator in the heading during
  create flows.

Also addresses the round-1 polish requests:
- Status messages moved above the version-selector row.
- Directional words removed from messages ("click Promote" not
  "click Promote below").
- Editor textarea is now editable on the bundled-default tab in
  edit mode (was read-only in round 1; the user couldn't type to
  draft a fork).

Back-compat: round-1 manifests without a `type` field are read as
type="full" automatically. Existing tests pass unchanged.

API extension: POST /api/role-templates/:name/versions accepts an
optional `type` field defaulting to "full". Invalid values return 400.

Tests:
- 41 unit tests in role-templates.test.ts (was 30) — augmented
  composition, boot refresh idempotency, full-versions-untouched,
  back-compat with round-1 manifests.
- 17 endpoint tests (was 15) — type validation in POST /versions.
- 845 total core+cli+web pass.

Pre-existing app.test.ts config-merge failure on main is unrelated.

Design doc + plan + CHANGELOG updated.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…match agent execution flow

The user spotted that the tab labelled "Workspace Process" is
functionally the **dev agent's** primary instruction template — the
file's content literally opens with "You are a dev agent working on
a cfcf-managed workspace. This document defines how you operate
within each iteration."

The historical name `process.md` predates the explicit per-role
instruction files (cfcf-architect-instructions.md, etc.) so it never
got renamed to `cfcf-dev-instructions.md`. The display name in the
Agents tab should reflect the role, not the historical filename. The
inline "Template file: process.md" hint on the page still surfaces
the real filename for users who grep the override directory.

Also reorders the tabs to match the natural agent execution
sequence within an iteration loop:
  Solution Architect → Developer → Judge → Reflection → Documenter

(Architect runs pre-loop and on refine_plan / NEEDS_REFINEMENT;
dev does the work; judge assesses; reflection optionally analyses
across iterations; documenter runs post-SUCCESS. Reading top-to-
bottom in the UI now mirrors the firing order.)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…e" claims + document new features

A documentation audit pass over all user-facing docs to align with
recent changes (items 6.30, 6.31, 6.33, 6.8 rounds 1+2).

Stale "manually-invoked SA via cfcf review = interactive" framing
removed from:
- README.md (top-level policy heads-up)
- docs/guides/installing.md (Claude Code install recommendation)
- docs/guides/cli-usage.md (cfcf init warnings section)
- docs/guides/workflow.md (adapter-choice block)
- docs/guides/troubleshooting.md (harness-policy warning entry)

Reality (verified in code 6.30): ALL architect spawns are headless
`claude -p` regardless of how they're invoked. `cfcf review` is just
a polling client to a server-side background spawn — there's no
`stdio: "inherit"` anywhere in the architect path. Only PA + HA
truly take over the user's shell. All five surfaces now reflect this.

Also fixed:
- docs/guides/installing.md: dropped "auto-architect" qualifier from
  the unattended-roles enumeration; architect is always unattended.

New feature documentation:
- docs/api/server-api.md: added `GET /api/agents/models`,
  `POST /api/agents/refresh-ollama-models` (item 6.33), and the full
  `/api/role-templates/*` surface (item 6.8).
- docs/guides/cli-usage.md: added `cfcf server reap` section
  (item 6.31, v0.21.0); ollama-models auto-refresh + button
  reference (item 6.33); five-tab web UI navigation overview
  (Workspaces / Memory / Agents / Settings / Help) including a brief
  description of the new Agents tab and its full+augmented version
  types.
- docs/guides/manual.md: expanded Agents-tab bullet to mention
  round-2 full vs augmented version types + execution-order tab
  layout.
- docs/README.md: refreshed the directory map with the design docs +
  guides that have been added since the last update
  (role-template-management.md, anthropic-policy.md, etc.).
- CLAUDE.md: added bullets for role-template management (item 6.8),
  orphan reaper (item 6.31), ollama auto-refresh (item 6.33), and
  the architect-always-unattended classification (item 6.30). File
  structure section now lists role-templates.ts, orphan-reaper.ts,
  ollama-detection.ts, AgentTemplatesPage, and the cfcf server reap
  CLI verb.

Plan + decisions-log + design + research files left unchanged —
those are historical and shouldn't be retroactively edited.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
… panel (25vh)

The single-textarea FullEditor was 60vh tall while the augmented-mode
"cf² standard template (read-only)" panel was 25vh. Switching between
the two views (e.g. Default tab → an augmented-version tab) felt
jarring because the bundled-default content rendered at noticeably
different heights.

Aligned FullEditor to 25vh as well. The textarea keeps `resize:
vertical` so users editing a long full version can drag it taller —
just lowers the floor height from 60vh to 25vh for consistency.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@fstamatelopoulos fstamatelopoulos merged commit 3afe2a0 into main May 9, 2026
3 checks passed
@fstamatelopoulos fstamatelopoulos deleted the iteration-6/role-template-management-6.8 branch May 9, 2026 06:57
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.

1 participant