| name | light-new-Feature |
| description | Turn "I want feature X" into a designed, sliced, test-driven Delphi implementation — align, PRD, vertical slices, red-green each (failing DUnitX test first), then hand to light-review-PostEdit / light-review-Full. Say "add a feature", "build feature X", "implement a new feature", "create a new screen/dialog/option". |
Delphi New Feature — Pipeline Orchestrator
This skill takes a feature from a one-line brief to a working, tested vertical slice.
You (the main thread) are the orchestrator. Most of the heavy lifting you do yourself
(the design interview, the PRD, the slicing), but you launch sub-agents for the two jobs that
must run in isolation: compiling (the light-compiler agent) and the final verification
(light-review-PostEdit, optionally light-review-Full). You never hand-run a build script.
It is the front-half mirror of light-review-Full: light-review-Full covers review → verify → fix → doc;
this skill covers align → PRD → slice → implement, then chains into those review skills.
Reuse LightSaber first — do not reinvent it
LightSaber exists to eliminate boilerplate. Before writing any new unit, class, or utility, assume
LightSaber already does it — and check. Hand-rolling something it provides is the most common avoidable
mistake here: untested code, drift from the user's conventions, a skipped mature implementation. When
you do reuse, uses the LightSaber unit rather than copying its code; when nothing fits, write new
code but say so explicitly ("no LightSaber unit covers X, so I am adding it").
Where to look (naming is Light<Framework>.<Layer>.<Feature>):
| Need | Look in |
|---|
| Strings, dates, files, streams, binary, INI, encoding, logging — platform-agnostic | LightCore.* — e.g. LightCore.pas (200+ string/date/form helpers), LightCore.IO.pas (files/folders/disks), LightCore.StreamBuff.pas (typed binary stream, drop-in TFileStream replacement), LightCore.Binary.pas, LightCore.INIFile.pas, LightCore.AppData.pas |
| Windows utilities — registry, shell, dialogs, system info, clipboard | LightVcl.Common.* |
| Downloads, email, HTML | LightVcl.Internet.* |
| Image processing, GDI, effects | LightVcl.Graphics.* |
| Visual VCL controls (80+: TrayIcon, StringGrid, spin edits, …) | LightVcl.Visual.* |
| FMX utilities / visual controls | LightFmx.Common.* / LightFmx.Visual.* |
| App lifecycle, GUI auto-save/restore, settings, single-instance, updater, uninstaller, EULA, translation | AppData (3-layer: TAppDataCore → TAppData → TLightForm), SaveForm/LoadForm, the Updater\, AutoTranslator\ units |
Fastest lookup — grep the generated index. c:\Projects\LightSaber\_Index.md is a flat, per-unit
list of every public routine (full signature + one-line comment) across the ~216 units. Grep it for the
operation (e.g. IncrementFileName, CopyFile, WrapString), then open the named unit to confirm
the current declaration — the index is a pointer (regenerated by Build_Index.cmd), not the source
of truth. If it does not settle it, read that repo's README.md / CLAUDE.md (do not guess unit
names); Demo\ apps and UnitTesting\Test.<Unit>.pas show each unit's real API.
Where this fits — short-circuit FIRST
Most feature requests do NOT need all six phases. Before anything else, size the task and pick
the lightest path that still gets feedback through the compiler. Over-planning a typo wastes the
user's time; under-planning a binary-compatibility change is expensive to undo.
| Task | What to run |
|---|
| Typo / one-line fix | Skip this skill. Edit the file, compile via the light-compiler agent, done. |
| Small feature, single unit, no persistence, no binary-compat | Tiny path (Phase 0 only): a 3–5 question align, then implement one slice red-green, compile, hand off. Skip the PRD and the slice-splitting. |
| Real feature (multi-unit, new form, persistence, or binary-compat impact) | Full path: Phases 1 → 5. |
| Bug, not a feature | Wrong skill. Trace and fix; then run /light-review-Full. Use /light-review-PostEdit to verify. |
If you are unsure which path, ask the user ONE sizing question and let them pick. When in doubt
between tiny and full, lean toward the path that surfaces the high-stakes Delphi decisions early
(binary-compatibility, the LightSaber-vs-app boundary, persistence format) — those are the ones
that are cheap to decide now and dear to fix later.
Phase 0 — Triage (always)
- Read
CLAUDE.md (the project's, and the global one already in context). Learn the conventions
so you do not ask the user anything CLAUDE.md already answers.
- Briefly scan both the current project and the LightSaber library
(
c:\Projects\LightSaber\) to see what already exists — is there a LightSaber unit (or an
existing form) that already does ~80% of this? Grep c:\Projects\LightSaber\_Index.md first
(the generated per-unit list of every public routine + signature) for the operation by keyword,
then open the named unit to confirm; fall back to the README.md only if the index does not
settle it. If more than ~3 lookups would be needed, launch the Explore agent
(subagent_type: "Explore") pointed at both trees and let it report back, rather than reading
files into this context. Carry what you find into the "Reuse" question in Phase 1.
- Decide the path (tiny vs full) using the table above. State the chosen path to the user in one
line, with the one or two facts that drove the decision (e.g. "Full path — this bumps a
TLightStream version, so binary-compatibility is in play.").
For the tiny path, do Phase 1 (capped at 5 questions), then jump straight to Phase 4
(implement one slice) and Phase 5 (hand off). Skip Phases 2 and 3.
For the full path, run Phases 1 → 5 in order.
Phase 0b — Brand-new application? (skeleton + bridge)
Only when the feature is a whole new application (no existing .dproj): do NOT hand-build a
skeleton. Copy a LightSaber VCL template, rename it, and add the Autopilot bridge — the full steps
(template choice, rename checklist, AppName/CompanyName, the bridge uses + StartBridge +
AUTOPILOT Debug define, MCP registration) live in references/new-app.md. Read that file and
follow it, then return here for the feature itself (Align → … → Implement), treating slice 1 as the
first real feature on top of the working template.
Existing app missing the bridge? Even for a feature on an existing program, if it has no Autopilot
bridge yet, add it now (section 2 of references/new-app.md) so the running app is drivable in Phase 5.
Phase 1 — Align (adaptive)
Drive a one-question-at-a-time design interview until you and the user share a design concept.
This phase does NOT produce a plan or code — only a shared understanding. The PRD comes next.
Adaptive sizing — how many questions:
| Feature size | Question cap |
|---|
| Tiny path (Phase 0 said so) | 5 |
| Single feature | ~15–25 |
| Major feature / new unit | ~30–40 |
Run the interview per the /light-new-Align skill — the canonical, standalone definition of this
step: one question at a time, each carrying your recommended answer; skip what you can answer
yourself into a running auto-decided list; highest-stakes first; no silent agreement. Its
Delphi topic checklist — Scope (app vs LightSaber), Reuse (LightSaber first), Binary-compatibility
(TLightStream Save/Load), Persistence, AppData/INI keys, Threading, Cross-platform, Layer & UI,
Tests, Out-of-scope — lives there; do not restate it here.
Two feature-flow specifics on top of the skill:
- Cap by the Phase 0 path — tiny path = 5 questions; otherwise size per the table above.
- Feed in the Phase 0 LightSaber-reuse finding as the high-stakes "Reuse" question: name the
candidate unit(s) and confirm the plan reuses them, so only the no-fit parts become new code.
End Phase 1 by printing the auto-decided list and the line: "Ready to write the PRD?"
(tiny path: "Ready to implement?"). Stop and wait.
Phase 2 — PRD (full path only)
Summarize the just-finished alignment into a Product Requirements Document.
- Locate the PRD template at
c:\AI\Claude Code\TEMPLATE FOLDER\PRD.md.
- Fill every section from the alignment conversation. Leave no
<placeholder>. If one section
genuinely cannot be filled, ask exactly ONE clarifying question, get the answer, then fill it.
- Save to
Issues\<short-feature-name>.md in the project. Create the Issues\ folder if it
does not exist.
- Print the saved path. Do NOT read the PRD back to the user — they were in the interview; verify
only the three high-stakes fields yourself (binary-compatibility impact, the AppData/INI key
list, the out-of-scope list) and flag anything that looks wrong.
A PRD that records a binary-compatibility decision (a TLightStream version bump, an INI key
migration) is an Architecture Decision Record — tell the user to keep it in the repository rather
than deleting it after the feature ships. Ordinary PRDs should be archived once the feature merges.
Phase 3 — Vertical slices (full path only)
Split the PRD into independently-grabbable issue files, each describing one vertical slice —
a wedge that cuts through every layer (FMX/DFM form → unit code → AppData persistence → DUnitX test).
- Slice 1 is the tracer bullet. It MUST compile, run, show one new control on screen, persist
one field, and have one DUnitX test. It touches every layer.
- Subsequent slices add functionality, not new layers.
- Vertical, never horizontal. The natural instinct is "all the types first, then all the logic,
then all the forms." That is horizontal layering — reject it. Horizontal ordering hides binary-
compatibility regressions until the last phase, when they are most expensive; vertical slicing
surfaces them in slice 1 while the design is fresh.
- A slice an AFK agent would take more than ~30 minutes to finish is too big — split it.
- A slice that needs reading five or more existing units before any code is written is too big — split it.
For each slice write Issues\<feature>-<NN>-<short-name>.md with this frontmatter and body:
---
issue: <NN>
feature: <feature name>
blocks: [<issue numbers this one blocks>]
blocked_by: [<issue numbers blocking this one>]
afk: true|false
---
# <slice title>
## Goal
<one sentence>
## Affected units
- <Unit.pas> — <what changes>
- <Form.pas> + <Form.fmx/.dfm> — <what changes>
## Definition of done
- Compiles clean (zero errors, warnings, hints) via the light-compiler agent
- DUnitX test <name> passes
- <UI verification step, if applicable>
afk: true for schema/logic/tests/internal refactors (no human taste needed). afk: false for
anything user-facing where layout or feel matters.
Print a summary: how many slices, what the DAG of blocks/blocked_by looks like, and which are
AFK vs human-in-loop. Then proceed to Phase 4 with slice 1.
Phase 4 — Implement, slice by slice (red-green)
Work the slices in DAG order (a slice with unfinished blocked_by cannot start). For each slice:
4a. Red — write the failing test first
- Find the test project (usually
UnitTesting\Tests.dproj). If there is none, do NOT guess a
layout — ask the user whether to set one up (template:
c:\AI\Claude Code\TEMPLATE FOLDER\UnitTesting (TEMPLATE)\), and wait.
- Write ONE failing
[Test] for the behavior this slice adds, following the /light-review-RedGreen
discipline (real assertion, never Assert.Pass as the sole assertion, test behavior not "the type
exists", a name that says what is verified — its canonical rules + banned list live there). Run its
red-green loop inline; do not invoke the skill per slice.
- Compile the test
.dproj through the light-compiler agent (see 4c), launch the test EXE
yourself, and confirm RED — the test must fail on its assertion (a DUnitX failure), NOT
fail to compile or error for an unrelated reason. If it reds for the wrong reason, fix the test
before writing any production code.
4b. Green — implement until it passes
- Write the production code for the slice. Reuse LightSaber before writing new code — if a
LightCore.* / LightVcl.* / LightFmx.* unit already does it (strings, files, streams, INI,
logging, AppData, a visual control, …), uses that unit instead of hand-rolling it; write new
code only where nothing fits, and note that you checked (see "Reuse LightSaber first"). Prefer
DFM/FMX form definitions over dynamic TButton.Create(Self) creation. Prefer concrete classes
over generics unless type safety truly demands a generic (e.g. TDictionary). Never delete
///-disabled code blocks.
- Compile the test project via the
light-compiler agent again, launch the test EXE, confirm
GREEN.
- Refactor only if needed, then re-run the test EXE to confirm it is still green.
- Compile the main project via the
light-compiler agent and iterate until it is clean —
zero errors, zero warnings, zero hints.
- Mark the slice's issue done. Move to the next non-blocked slice.
4c. Compiling — via the light-compiler agent
Compile ONLY via the light-compiler agent (subagent_type: "light-compiler") — never build by
hand (global CLAUDE.md rule). Give it the .dproj:
- the test
.dproj (e.g. UnitTesting\Tests.dproj) for the red/green checks in 4a/4b;
- the main
.dproj for the clean-build check in step 7.
It returns structured JSON (status + per-issue file/line/col + source context) — read it, fix, call
again until clean. The agent compiles and reports only; launching the test EXE for DUnitX counts is
your job, after it reports a clean test build. If the target EXE is locked by a running app, tell the
agent to use --test (it builds to a temp folder) rather than killing the process.
Phase 5 — Hand off (verify, drive, review)
The implementation is done. Now verify it with the existing pipeline rather than re-checking it here.
-
Invoke the light-review-PostEdit skill (via the Skill tool). It verifies every edit you
made this session — that each change matches its intent, broke nothing observable, missed no call
sites, and broke no DFM/FMX bindings — reverts anything that does not hold up, and runs the
tests/compile. Capture what it reports.
-
New app? Run the standards gate. When this run created a new application, launch the
light-code-StyleChecker agent (Agent tool, subagent_type: "light-code-StyleChecker") over the new
app's own .pas / .dpr files to confirm the code meets the user's standards (.Free →
FreeAndNil, no with, no bare except, no Application.ProcessMessages, no stray globals,
spacing, etc.). Apply the fixes it surfaces, then re-compile via the light-compiler agent.
Scope note: this agent's own description aims it at imported/3rd-party code and points at
light-review-Full for "our own code." The user has explicitly asked for it as the standards check
on every new app, so run it here for that purpose — a fast convention gate on the fresh
skeleton + slice-1 code. The deep correctness pass is still light-review-Full (next step). Do not
run the style-checker on the LightSaber template units it copied in — only on the app's own code.
-
Drive the running app through the Autopilot MCP (smoke-test the feature). The app is bridge-
enabled (Phase 0b / references/new-app.md), so test it for real instead of only asking the user to click:
- Build the
AUTOPILOT Debug config via the light-compiler agent and launch the EXE (or, if it
is already running, just attach).
mcp__autopilot__list_tree to find the new control(s) this feature added.
- Exercise the feature:
mcp__autopilot__click / set_text / set_checked / execute_action
on the new controls, then assert the result with mcp__autopilot__get_text /
read_property (cheap — prefer these over screenshots). Use wait_for for async work.
mcp__autopilot__screenshot only for a layout/visual check you cannot read structurally.
- Close via the app's File→Exit / close button (a
click) so AutoState/INI is saved; kill the
process only if it hangs.
- Preconditions / fallbacks: this needs the
mcp__autopilot__* tools loaded this session.
If they are absent (server not yet registered, or registered only this session), say so and fall
back to the manual-QA reminder — do NOT hand-roll a UI driver. Read
c:\Projects\Projects AI\Autopilot for Delphi\AI-INSTRUCTIONS.md for the tool reference and the
efficiency rules (bundle independent calls into one turn; count=N for repeats).
-
Optionally invoke /light-review-Full on the .pas files the feature added or changed — a
real correctness review in fresh context (deeper than the step-2 style gate). Offer this for a
full-path feature; for a tiny-path change light-review-PostEdit alone is usually enough. Ask the
user before launching it if you are unsure, since it is a multi-agent pass.
-
Print one short consolidated summary:
- Path taken — tiny or full; new app or feature-on-existing.
- What was built — the slices completed and the units/forms touched.
- Tests — which DUnitX tests now pass (the counts you read from the EXE).
- Compile — clean or not, from the
light-compiler agent.
- Standards gate —
light-code-StyleChecker result (new apps): issues found/fixed, or "n/a — not
a new app".
- Live smoke-test — what you drove via the Autopilot MCP and what it showed, or why it was
skipped (tools not loaded).
- Verification — what
light-review-PostEdit held / adjusted / reverted.
- Needs your attention — open questions, human-in-loop slices not yet done, anything flagged.
- Manual QA reminder — even after the MCP smoke-test, UI feel, layout, and the messy
unhappy paths the bridge cannot reach (focus/validation, hover, real drag-drop, IME) are
non-delegable; remind the user to click through the new feature.
Rules
- Short-circuit before you start. Match the phases to the task size. A typo does not get a PRD.
- Reuse LightSaber before writing new code. For every non-trivial need, check for an existing
LightCore.* / LightVcl.* / LightFmx.* unit first (it exists to kill boilerplate); uses it
instead of hand-rolling, and write new code only where nothing fits — stating that you checked.
Consult c:\Projects\LightSaber\README.md rather than guessing unit names.
- Compile ONLY through the
light-compiler agent. Never Build.cmd / BuildTests.cmd /
MSBuild / dcc32 by hand. This is the single most important rule in this skill.
- Red before green, always. The failing test is written and confirmed RED before any
production code. A test written after the implementation is tautological — it confirms the code
does what the code says, not what the requirement says.
Assert.Pass as a sole assertion is banned.
- Vertical slices, never horizontal. Slice 1 touches every layer and runs. Correct the
"all-the-schema-first" instinct every time it appears.
- Surface the high-stakes Delphi decisions first — binary-compatibility (
TLightStream
versioning), the LightSaber-vs-app boundary, persistence format, AppData/INI keys. These are
cheap to decide up front and expensive to retrofit.
- Every app must be Autopilot-drivable. Ensure the bridge (Phase 0b /
references/new-app.md) before implementing — new
apps and existing apps that lack it — so the running program can be tested via the
mcp__autopilot__* tools, not just compiled (setup: references/new-app.md). The AUTOPILOT
define lives on Debug only; Release pays zero cost.
- New app → run the
light-code-StyleChecker standards gate (Phase 5) on the app's own code before
finishing. Then drive the running app through the Autopilot MCP to smoke-test the feature; manual
QA for feel still follows.
- You do most of the work; sub-agents do compiling and final verification. Use
Explore for a
broad codebase scan, light-compiler for every build, and light-review-PostEdit / light-review-Full
for the hand-off.
- Delphi vocabulary throughout —
nil not null, record not struct, try/except not
try/catch, anonymous method not lambda, unit not module, enumeration not enum, RTTI not
reflection.