From al-dev-toolkit
Plan a BC feature before implementing it. Use when the user asks for a new feature, multi-object change, or significant AL implementation that needs design — involves 3+ files, new tables/pages/codeunits, event subscriptions, or architectural decisions. Produces a plan file, does NOT write code. Do NOT use for simple 1-2 file changes (use quick) or vague ideas (use brainstorming).
How this skill is triggered — by the user, by Claude, or both
Slash command
/al-dev-toolkit:al-planning <description of what to build><description of what to build>The summary Claude sees in its skill listing — used to decide when to auto-load this skill
You are the orchestrator. Understand what the user wants, research the base app, design the solution, write a plan file. Do NOT implement anything.
You are the orchestrator. Understand what the user wants, research the base app, design the solution, write a plan file. Do NOT implement anything.
- Do NOT write AL code, create .al files, or invoke implementation during planning. The ONLY output is a plan file and a summary. - Do NOT read source files to verify researcher results — trust them. If a summary seems incomplete, spawn another targeted researcher instead. - Do NOT spawn subagents to write the plan — the orchestrator writes it directly. - Do NOT read large base app source files directly. All codebase research is done by researcher agents. - Exception: project config files (app.json, CodeCop.json, .github/copilot-instructions.md) and context files (.github/context/) are small — read those directly./quick/quick or direct conversation/quickStep 0 — Specificity gate:
Before anything else, evaluate the user's request. A plannable request names a specific feature, behavior, or object to build. A vague request does not.
| Specific (proceed) | Vague (redirect to /brainstorm) |
|---|---|
| "Add credit limit validation that blocks sales orders" | "Improve the sales process" |
| "Extend customer card with a rating system" | "Make customer management better" |
| "Block posting when item is blocked on location" | "We need better inventory controls" |
| "Add a field to track last shipment date on sales header" | "Do something with shipments" |
If vague: Stop planning. Tell the user:
This request is too broad to plan directly. Run
/brainstorm [your idea]first — it will help refine the idea into a specific, plannable requirement through a short conversation.
If specific: Continue to step 1.
Steps 1-5:
app.json (ID ranges, dependencies), CodeCop.json (mandatoryAffixes), .github/copilot-instructions.md (BC version, deployment target, project rules). If deployment target is missing, ask the user..github/context/ — if context files exist, read referenced ones, list unreferenced ones and ask if relevant.src/**/*.al — know what already exists (names only).Run parallel subagents using the researcher agent (with Sonnet) to investigate the base app. You know BC — use your domain knowledge to decide what needs researching.
Always investigate:
al_find_references with referenceType: extends)Researcher spawn prompts — the researcher agent definition bakes in the Detective personality and MCP lookup instructions. Only pass:
Fill gaps before designing. If research has holes, run targeted follow-up researcher subagents. Use #microsoft-learn/microsoft_docs_search / #microsoft-learn/microsoft_docs_fetch for quick documentation lookups.
Design the solution directly from research findings. Do NOT delegate design to subagents.
Dispatch context detection: Before writing the plan, check $ARGUMENTS for a marker of the form [DISPATCH_CONTEXT: do-task taskID=<N>]. If present, extract <N> and use it for the filename and plan.id per the table below.
Location:
.github/plans/plan-<YYYYMMDD-HHMM>.md with plan.id: plan-YYYYMMDD-HHMM[DISPATCH_CONTEXT: do-task taskID=<N>] is present: .github/plans/task-<N>-plan.md with plan.id: task-<N>-planThe plan must be self-contained — a coder with only the plan file must be able to implement.
Plan format — YAML frontmatter + prose.
The file starts with a YAML frontmatter block (machine-readable) followed by the prose body (human-readable). The frontmatter shape, field reference, object type enum, status lifecycle, authority rule, and writer discipline checklist are defined in plan-schema.md — read it before writing a plan.
Skeleton:
---
plan:
id: plan-YYYYMMDD-HHMM
created: <ISO 8601 UTC>
feature: "[Feature Name]"
status: draft
project:
bc_version: "[version]"
deployment: [SaaS|OnPrem|Both]
object_id_range: [<min>, <max>]
mandatory_affixes: [<affixes from CodeCop.json>]
requirements:
- id: R1
text: "..."
research_topics_covered:
- "..."
objects:
- key: <StableKey>
type: <object type>
id: <int>
name: "<Exact AL Object Name>"
file: "src/<folder>/<Name>.<Type>.al"
extends: <null or "BaseName">
depends_on: []
satisfies: [R1]
implementation_sequence: [<keys in order>]
open_questions: []
---
# Plan: [Feature Name]
## Requirement
[User's request, clarified]
## Design Decisions
1. [Decision] — [Rationale]
## Objects
### [Object Name]
- **Type / ID / Name / File / Extends**
- **Fields:** field ID, name, type, DataClassification for each
- **Event Subscriptions:** full AL signatures, copy-paste ready
- **Procedures:** name, parameters with types, return type, one-line purpose
- **Key Logic:** what this object does and why
## Implementation Sequence
1. [Object] — [why this order]
## Event Subscriptions
[Full signatures, copy-paste ready]
## Open Questions
[Unresolved items, if any]
Writer discipline — run before announcing completion. After writing the plan file, run the full writer discipline checklist in plan-schema.md under the "Writer discipline" section. It covers prose/YAML bidirectional matching, requirement coverage, object ID range, depends_on and implementation_sequence key integrity, plan.status = draft, objects[].type enum conformance, and objects[].extends non-null pairing with extension types.
If any check fails: fix silently if the fix is mechanical (regenerate a missing prose heading, correct an out-of-range ID against app.json); ask the user if the fix requires a design decision (e.g., prose mentions an object with no YAML entry and no obvious key/type).
Skip this step when project.deployment == SaaS — SaaS publishers get unlimited extension ranges, so minting new codeunits per concern is fine. Also skip when the plan has no objects[] entries with type: codeunit (nothing to review).
When project.deployment is OnPrem or Both and the plan contains new codeunits, run a subagent using the codeunit-reuse-analyzer agent (with Sonnet). OnPrem object IDs are a finite resource, and many "new" codeunits in a plan can be merged into an existing project codeunit without loss of clarity.
Dispatch:
Response: a markdown table of verdicts, one row per candidate codeunit — KEEP_NEW or MERGE_INTO <name> with rationale.
If every verdict is KEEP_NEW: note the check passed in the handoff summary and continue.
If any MERGE_INTO: present the verdict table to the user verbatim and ask, merge-by-merge, which to apply. For each accepted merge:
objects[]depends_on listed the merged key — drop that entry (the target is pre-existing and therefore not tracked in objects[])implementation_sequence## Objects section, move the merged codeunit's description under the target's existing ### <Name> heading (as new procedures), then delete the merged ### <Name> headingDo not apply merges silently — the user decides each one. If the user rejects all merges, leave the plan untouched.
Write LATEST pointer: Save the plan file path to .github/plans/LATEST (overwrite if exists). This allows /implement to find the most recent plan without manual path entry. Create the .github/plans/ directory if it doesn't exist.
If [DISPATCH_CONTEXT: do-task taskID=<N>] was present in $ARGUMENTS: the caller (/do-task) will continue to al-implementation itself. Present a brief plan summary (design decisions, file list, open questions) and STOP — do not present the 3-option prompt. Return control to the caller.
Otherwise present the plan summary (design decisions, file list, open questions), then ask the user:
Plan saved to
[plan-file-path]. Three options:1) Fresh context implementation — I'll clear context and start
/implementwith only the plan file. Best for large plans where research consumed a lot of context.2) Continue in this session — I'll dispatch coder subagents right now. Faster, but orchestrator keeps the research context in memory.
3) Review first — I'll stop here. Review the plan, then run
/implement [plan-path]when ready.
If 1: Run a subagent to act as an implementation orchestrator — it reads the al-implementation skill and the plan file. This subagent gets a fresh context window — no research baggage. It handles the full cycle: coders, build, review. Report its results when done. If 2: Invoke the al-implementation skill and execute it directly in this session with the plan already in context. If 3: Stop.
$ARGUMENTS
Guides creation, editing, and verification of skills for AI coding agents using test-driven development with subagent scenarios. Use when authoring or debugging skills.
npx claudepluginhub andreipopaarggo/al-dev-toolkit --plugin al-dev-toolkit