Skip to content

Commit add7ca8

Browse files
Magnus Hartvig Grønbechclaude
andcommitted
feat: add Documentation Maintenance GitHub Action
Runs Copilot CLI with Claude Opus 4.6 and the al-docs plugin on PRs. Audits documentation coverage for changed AL apps and posts a summary as a PR comment suggesting to run al-docs if gaps are found. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent b7803d3 commit add7ca8

8 files changed

Lines changed: 1466 additions & 0 deletions

File tree

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
name: 'Documentation Maintenance'
2+
3+
on:
4+
pull_request:
5+
branches: ['main', 'releases/*', 'features/*']
6+
paths: ['src/**/*.al']
7+
8+
concurrency:
9+
group: docs-${{ github.event.pull_request.number }}
10+
cancel-in-progress: true
11+
12+
permissions:
13+
actions: read
14+
contents: read
15+
pull-requests: write
16+
17+
jobs:
18+
AuditDocs:
19+
if: github.event.pull_request.head.repo.full_name == github.event.pull_request.base.repo.full_name
20+
runs-on: ubuntu-latest
21+
timeout-minutes: 30
22+
env:
23+
COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GH_TOKEN }}
24+
steps:
25+
- name: Checkout
26+
uses: actions/checkout@v4
27+
with:
28+
fetch-depth: 0
29+
ref: ${{ github.event.pull_request.head.sha }}
30+
31+
- name: Setup Node.js
32+
uses: actions/setup-node@v4
33+
34+
- name: Install Copilot CLI
35+
run: npm install -g @github/copilot
36+
37+
- name: Install al-docs plugin
38+
run: |
39+
copilot plugin install ./tools/al-docs-plugin
40+
copilot plugin list
41+
42+
- name: Find changed apps
43+
id: scope
44+
run: |
45+
MERGE_BASE=$(git merge-base ${{ github.event.pull_request.base.sha }} ${{ github.event.pull_request.head.sha }})
46+
CHANGED=$(git diff --name-only "$MERGE_BASE"..${{ github.event.pull_request.head.sha }} -- '*.al')
47+
48+
if [ -z "$CHANGED" ]; then
49+
echo "count=0" >> "$GITHUB_OUTPUT"
50+
exit 0
51+
fi
52+
53+
APPS=$(echo "$CHANGED" | while read -r f; do
54+
d=$(dirname "$f")
55+
while [ "$d" != "." ]; do
56+
[ -f "$d/app.json" ] && echo "$d" && break
57+
d=$(dirname "$d")
58+
done
59+
done | sort -u)
60+
61+
COUNT=$(echo "$APPS" | wc -l | tr -d ' ')
62+
echo "count=$COUNT" >> "$GITHUB_OUTPUT"
63+
echo "apps<<EOF" >> "$GITHUB_OUTPUT"
64+
echo "$APPS" >> "$GITHUB_OUTPUT"
65+
echo "EOF" >> "$GITHUB_OUTPUT"
66+
67+
- name: Run al-docs audit
68+
if: steps.scope.outputs.count != '0'
69+
id: audit
70+
run: |
71+
REPORT=""
72+
while IFS= read -r APP_PATH; do
73+
[ -z "$APP_PATH" ] && continue
74+
APP_NAME=$(jq -r '.name // "unknown"' "$APP_PATH/app.json" 2>/dev/null || echo "unknown")
75+
echo "Auditing $APP_NAME at $APP_PATH..."
76+
77+
OUTPUT=$(timeout 300 copilot -p \
78+
"Look at the AL app at $APP_PATH. Check if it has a CLAUDE.md or docs/ directory.
79+
Count the AL objects (tables, codeunits, pages). Reply in 2-3 sentences:
80+
what you found, whether docs exist, and if the developer should run al-docs." \
81+
--model claude-opus-4.6 \
82+
-s \
83+
--no-ask-user \
84+
--autopilot \
85+
--allow-all-paths \
86+
--allow-tool=read \
87+
--allow-tool=glob \
88+
--allow-tool=grep \
89+
2>&1) || true
90+
91+
if echo "$OUTPUT" | grep -qi "missing\|no documentation\|should.*run\|does not have\|0%\|no CLAUDE"; then
92+
REPORT="$REPORT
93+
**$APP_NAME** (\`$APP_PATH\`): $OUTPUT
94+
"
95+
fi
96+
done <<< '${{ steps.scope.outputs.apps }}'
97+
98+
if [ -n "$REPORT" ]; then
99+
echo "has_gaps=true" >> "$GITHUB_OUTPUT"
100+
echo "report<<EOF" >> "$GITHUB_OUTPUT"
101+
echo "$REPORT" >> "$GITHUB_OUTPUT"
102+
echo "EOF" >> "$GITHUB_OUTPUT"
103+
else
104+
echo "has_gaps=false" >> "$GITHUB_OUTPUT"
105+
fi
106+
107+
- name: Post audit report
108+
if: steps.audit.outputs.has_gaps == 'true'
109+
env:
110+
GH_TOKEN: ${{ github.token }}
111+
run: |
112+
gh pr comment ${{ github.event.pull_request.number }} --body "$(cat <<'COMMENT'
113+
### Documentation gaps detected
114+
115+
The following apps changed in this PR but have missing or incomplete documentation:
116+
117+
${{ steps.audit.outputs.report }}
118+
119+
Consider running \`/al-docs init\` or \`/al-docs update\` on these apps to generate documentation before merging.
120+
COMMENT
121+
)"
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"name": "al-docs",
3+
"version": "0.1.0",
4+
"description": "AL codebase documentation generator - bootstrap, update, and audit hierarchical docs for Business Central AL apps",
5+
"author": {
6+
"name": "NAV Team"
7+
},
8+
"keywords": ["al", "business-central", "documentation", "docs"]
9+
}

tools/al-docs-plugin/README.md

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
# AL Docs plugin
2+
3+
AL codebase documentation generator that bootstraps, updates, and audits hierarchical docs for Business Central AL apps. Produces CLAUDE.md orientation files and AL-specific docs (data-model.md, business-logic.md, patterns.md) at app and subfolder levels.
4+
5+
**Version:** 0.1.0
6+
7+
## Skills
8+
9+
| Skill | Command | Description |
10+
|-------|---------|-------------|
11+
| AL Docs | `/al-docs` | Bootstrap, update, or audit AL codebase documentation |
12+
13+
## Usage
14+
15+
```
16+
/al-docs # Bootstrap docs (same as /al-docs init)
17+
/al-docs init # Bootstrap documentation for AL app or folder
18+
/al-docs init "path/to/app" # Bootstrap docs for a specific path
19+
/al-docs update # Incrementally refresh docs based on changes
20+
/al-docs audit # Read-only gap analysis without writing files
21+
```
22+
23+
## Modes
24+
25+
### 1. Init (`/al-docs init`)
26+
27+
Bootstraps a complete documentation hierarchy through five phases:
28+
29+
1. **Discovery** -- launches 3 parallel sub-agents to analyze the AL codebase:
30+
- Agent 1: app structure, `app.json` metadata, object inventory by type and subfolder
31+
- Agent 2: data model -- tables, relationships, enums, keys, conceptual model
32+
- Agent 3: business logic, patterns, event architecture, subfolder scoring
33+
2. **Documentation map** -- presents every file to create for user approval
34+
3. **Exit plan mode** -- unlocks write access
35+
4. **Generation** -- parallel sub-agents write docs grouped by scope
36+
5. **Cross-referencing** -- verifies links and consistency
37+
38+
### 2. Update (`/al-docs update`)
39+
40+
Incrementally refreshes docs based on git changes:
41+
42+
1. **Detect changes** -- determines baseline and gets changed `.al` files
43+
2. **Map changes** -- maps AL object types to affected doc files (table changes -> data-model.md, codeunit changes -> business-logic.md, etc.)
44+
3. **Targeted regeneration** -- presents update plan for approval, then updates affected docs only
45+
4. **Staleness report** -- summarizes changes and flags potentially stale sections
46+
47+
### 3. Audit (`/al-docs audit`)
48+
49+
Read-only gap analysis:
50+
51+
- Launches 3 parallel subagents to inventory objects, existing docs, and score subfolders
52+
- Compares expected documentation against what exists
53+
- Reports coverage percentage, missing files, and non-standard patterns
54+
- Provides prioritized recommendations
55+
56+
## Generated doc types
57+
58+
| File | Purpose |
59+
|------|---------|
60+
| `CLAUDE.md` | Orientation: app purpose, dependencies, structure, key objects |
61+
| `data-model.md` | What the app models, table relationships, key fields, enums |
62+
| `business-logic.md` | Codeunits, processing flows, event pub/sub, integration points |
63+
| `patterns.md` | Locally applied patterns (IsHandled, TryFunction, etc.) |
64+
65+
## Documentation levels
66+
67+
| Level | Location | Content |
68+
|-------|----------|---------|
69+
| App (has `app.json`) | `/CLAUDE.md`, `/docs/` | App-wide overview, full data model, cross-cutting logic |
70+
| Subfolder (score 7+) | `/[subfolder]/docs/` | CLAUDE.md + at least one additional doc |
71+
| Subfolder (score 4-6) | `/[subfolder]/docs/` | CLAUDE.md only |
72+
73+
## Subfolder scoring
74+
75+
Subfolders are scored 0-10 based on AL object count, table count, codeunit count, event presence, and extension objects:
76+
77+
- **MUST_DOCUMENT (7+)**: CLAUDE.md plus at least one additional file
78+
- **SHOULD_DOCUMENT (4-6)**: CLAUDE.md only
79+
- **OPTIONAL (1-3)**: Skipped
80+
81+
## Plugin structure
82+
83+
```
84+
al-docs-plugin/
85+
├── .claude-plugin/
86+
│ └── plugin.json
87+
├── README.md
88+
└── skills/
89+
└── al-docs/
90+
├── SKILL.md # Router -- dispatches to the correct mode
91+
├── al-docs-init.md # Mode 1: full bootstrap
92+
├── al-docs-update.md # Mode 2: incremental update
93+
└── al-docs-audit.md # Mode 3: read-only audit
94+
```
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
---
2+
name: al-docs
3+
description: This skill should be used when the user asks to "document AL code", "generate docs for this app", "create documentation for this extension", "document this BC app", "set up docs for this AL project", "refresh my docs after code changes", "what documentation is missing", or wants to bootstrap, update, or audit documentation for a Business Central AL codebase. Generates hierarchical docs (CLAUDE.md, data-model.md, business-logic.md, extensibility.md, patterns.md) tailored to AL object types, table relationships, event architecture, and extension patterns.
4+
allowed-tools: Read, Write, Edit, Glob, Grep, Bash(*)
5+
argument-hint: "[init|update|audit] [path]"
6+
---
7+
8+
# AL Documentation Generator
9+
10+
Generate, update, and audit hierarchical documentation for Business Central AL codebases. Produces documentation adapted to AL object types, table relationships, event-driven architecture, and extension patterns.
11+
12+
## Usage
13+
14+
```
15+
/al-docs # Bootstrap docs (same as /al-docs init)
16+
/al-docs init # Bootstrap documentation for AL app or folder
17+
/al-docs init "path/to/app" # Bootstrap docs for a specific path
18+
/al-docs update # Incrementally refresh docs based on changes
19+
/al-docs audit # Read-only gap analysis without writing files
20+
```
21+
22+
## Routing
23+
24+
Based on the argument provided, load and follow the appropriate mode file. Always read the full mode file before executing -- never run from memory.
25+
26+
### If argument starts with "init" (or no argument)
27+
28+
Read and follow `skills/al-docs/al-docs-init.md` from the plugin directory. Pass any remaining text as the target path.
29+
30+
### If argument starts with "update"
31+
32+
Read and follow `skills/al-docs/al-docs-update.md` from the plugin directory. Pass any remaining text as options (baseline commit, path filter).
33+
34+
### If argument starts with "audit"
35+
36+
Read and follow `skills/al-docs/al-docs-audit.md` from the plugin directory. Pass any remaining text as the target path.
37+
38+
## Mode files
39+
40+
| Mode | Command | File |
41+
|------|---------|------|
42+
| Init | `/al-docs init` | `skills/al-docs/al-docs-init.md` |
43+
| Update | `/al-docs update` | `skills/al-docs/al-docs-update.md` |
44+
| Audit | `/al-docs audit` | `skills/al-docs/al-docs-audit.md` |
45+
46+
## What gets generated
47+
48+
Documentation is hierarchical -- more general at the app level, more specific deeper in the tree.
49+
50+
### Doc types
51+
52+
| File | Purpose |
53+
|------|---------|
54+
| `CLAUDE.md` | Mental model: what this area does, how it works, and non-obvious things to know |
55+
| `data-model.md` | How tables relate and why -- intent, design decisions, gotchas (not field lists). Always includes a mermaid ER diagram. |
56+
| `business-logic.md` | Processing flows as narrative -- decision points, error handling. Includes mermaid flowcharts for processes with branching. |
57+
| `extensibility.md` | Extension points, events, interfaces -- how to customize without modifying core code |
58+
| `patterns.md` | Non-obvious coding patterns (including legacy patterns to avoid in new code) |
59+
60+
### Documentation levels
61+
62+
| Level | Location | Content |
63+
|-------|----------|---------|
64+
| App (has `app.json`) | `/CLAUDE.md`, `/docs/` | App-wide overview, full data model, cross-cutting logic, extensibility, and patterns |
65+
| Subfolder at any depth (scored 7+) | `/[path]/docs/` | CLAUDE.md + at least one of data-model/business-logic/extensibility/patterns |
66+
| Subfolder at any depth (scored 4-6) | `/[path]/docs/` | CLAUDE.md only |
67+
68+
### Scope detection
69+
70+
1. **Target has `app.json`** -- document the entire app as the project level
71+
2. **Target is a folder without `app.json`** -- document that folder; if subfolders at any depth have enough substance, they get their own docs
72+
3. **Recursive evaluation** -- subfolders are evaluated recursively; a subfolder's subfolder can be documented independently if it scores high enough
73+
4. **Locality principle** -- deeper docs are more specific; higher docs are more general, pointing down to specifics
74+
75+
## AL object types and scoring
76+
77+
For the full list of AL object types, subfolder scoring criteria, and change-to-doc mapping, read `skills/al-docs/references/al-scoring.md`.
78+
79+
Summary of scoring classifications:
80+
81+
- **MUST_DOCUMENT (7+)**: CLAUDE.md + at least one of data-model/business-logic/extensibility/patterns
82+
- **SHOULD_DOCUMENT (4-6)**: CLAUDE.md only
83+
- **OPTIONAL (1-3)**: Skip
84+
85+
## Microsoft Docs MCP
86+
87+
During discovery, use the Microsoft Learn MCP tools (`microsoft_docs_search`, `microsoft_docs_fetch`, `microsoft_code_sample_search`) to research the feature area being documented. This provides context about the intended behavior, official terminology, and design rationale that may not be obvious from the source code alone.
88+
89+
- Search for the app's feature area (e.g., "Business Central Shopify connector", "Business Central inventory management") to understand what the feature is supposed to do
90+
- Use this context to write better "How it works" and "Things to know" sections
91+
- **Source code is the source of truth.** Microsoft docs may be outdated or describe planned behavior that differs from the implementation. When docs conflict with what the code actually does, trust the code. Note the discrepancy in documentation if it's meaningful (e.g., "the docs describe X, but the implementation does Y").
92+
93+
## Critical rules
94+
95+
1. **Always read the mode file** -- never attempt to run a mode from memory
96+
2. **User approves before writing** -- present the documentation map or update plan first
97+
3. **Based on real analysis** -- every statement must trace back to actual AL code read during discovery
98+
4. **Preserve existing content** -- when updating, add/edit sections, never delete human-written content
99+
5. **Locality** -- document as locally as possible, getting more general going up the tree
100+
6. **No mechanical listings** -- never list fields, procedures, or AL objects that an LLM can read from code. Capture intent, relationships, gotchas, and design decisions.
101+
7. **Concise over comprehensive** -- shorter docs with real knowledge beat longer docs that list everything
102+
8. **Use Microsoft Docs MCP** -- query Microsoft Learn during discovery to understand feature intent, but always trust source code over docs when they conflict

0 commit comments

Comments
 (0)