beacon-framework 1.2.2__tar.gz → 1.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/PKG-INFO +1 -1
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/pyproject.toml +3 -1
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/__init__.py +1 -1
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/cli.py +22 -7
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/manifest.py +6 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/resources/integrations/claude_code/commands/beacon/roadmap.md +3 -1
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/roadmap.py +36 -14
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/.gitignore +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/BEACON.md +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/LICENSE +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/README.md +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/pragmatic-principles.md +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/__main__.py +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/bullet.py +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/docs.py +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/doctor.py +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/epic.py +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/installer.py +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/integrations/__init__.py +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/integrations/claude_code.py +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/integrations/release.py +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/language.py +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/resources/beacon.md +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/resources/help/commands.md +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/resources/help/doctor.md +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/resources/help/git-flow.md +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/resources/help/phases.md +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/resources/help/quickstart.md +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/resources/integrations/claude_code/CLAUDE.md.fragment +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/resources/integrations/claude_code/agents/beacon-reviewer.md +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/resources/integrations/claude_code/commands/beacon/constitution.md +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/resources/integrations/claude_code/commands/beacon/continue.md +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/resources/integrations/claude_code/commands/beacon/implement.md +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/resources/integrations/claude_code/commands/beacon/plan.md +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/resources/integrations/claude_code/commands/beacon/prd.md +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/resources/integrations/claude_code/commands/beacon/review.md +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/resources/integrations/claude_code/commands/beacon/seed.md +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/resources/integrations/claude_code/commands/beacon/specify.md +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/resources/integrations/claude_code/commands/beacon/status.md +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/resources/integrations/claude_code/commands/beacon/tasks.md +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/resources/integrations/claude_code/commands/design/diagram.md +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/resources/integrations/claude_code/commands/design/evaluate.md +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/resources/integrations/claude_code/commands/design/wardley.md +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/resources/integrations/claude_code/commands/git/feature.md +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/resources/integrations/claude_code/commands/git/pr.md +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/resources/integrations/claude_code/commands/git/release.gitflow.md +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/resources/integrations/claude_code/commands/git/release.trunk.md +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/resources/integrations/claude_code/commands/init.md +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/resources/integrations/claude_code/settings.json +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/resources/integrations/claude_code/skills/beacon-build/SKILL.md +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/resources/integrations/claude_code/skills/beacon-design/SKILL.md +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/resources/integrations/claude_code/skills/beacon-seed/SKILL.md +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/resources/integrations/claude_code/skills/beacon-ship/SKILL.md +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/resources/integrations/release/PUBLISHING.gitflow.md +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/resources/integrations/release/PUBLISHING.trunk.md +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/resources/integrations/release/psr_config.gitflow.toml +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/resources/integrations/release/psr_config.trunk.toml +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/resources/integrations/release/workflows/release.gitflow.yml +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/resources/integrations/release/workflows/release.trunk.yml +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/resources/languages/node.toml +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/resources/languages/python.toml +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/resources/project-management/.beacon/doctor.toml.example +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/resources/project-management/ADRs/ADR-000-template.md +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/resources/project-management/ADRs/README.md +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/resources/project-management/Background/00-problem-statement.md +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/resources/project-management/Background/01-final-architecture-document.md +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/resources/project-management/Roadmap/README.md +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/resources/project-management/Roadmap/archive/.gitkeep +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/resources/project-management/Roadmap/epics/.gitkeep +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/resources/project-management/Roadmap/epics/EPIC-TEMPLATE.md +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/resources/project-management/Roadmap/epics/archive/.gitkeep +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/resources/project-management/Work/README.md +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/resources/project-management/Work/analysis/.gitkeep +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/resources/project-management/Work/branches/.gitkeep +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/resources/project-management/Work/planning/.gitkeep +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/resources/project-management/Work/sessions/.gitkeep +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/resources/roadmap_template.html +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/resources/user-facing-docs/README.md +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/resources/user-facing-docs/explanation/index.md +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/resources/user-facing-docs/how-to/index.md +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/resources/user-facing-docs/reference/index.md +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/resources/user-facing-docs/tutorials/getting-started.md +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/seed.py +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/upgrader.py +0 -0
- {beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/validate.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: beacon-framework
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.3.0
|
|
4
4
|
Summary: Light-touch, pragmatic, artifact-driven framework for AI-assisted software delivery
|
|
5
5
|
Project-URL: Repository, https://github.com/darth-veitcher/beacon
|
|
6
6
|
Author: darth-veitcher
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "beacon-framework"
|
|
7
|
-
version = "1.
|
|
7
|
+
version = "1.3.0"
|
|
8
8
|
description = "Light-touch, pragmatic, artifact-driven framework for AI-assisted software delivery"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "MIT"
|
|
@@ -77,6 +77,7 @@ Repository = "https://github.com/darth-veitcher/beacon"
|
|
|
77
77
|
|
|
78
78
|
|
|
79
79
|
|
|
80
|
+
|
|
80
81
|
|
|
81
82
|
|
|
82
83
|
[tool.hatch.build.targets.wheel]
|
|
@@ -186,6 +187,7 @@ exclude_commit_patterns = ["^chore\\(release\\):"]
|
|
|
186
187
|
|
|
187
188
|
|
|
188
189
|
|
|
190
|
+
|
|
189
191
|
|
|
190
192
|
|
|
191
193
|
[dependency-groups]
|
|
@@ -1271,8 +1271,8 @@ def roadmap_export(
|
|
|
1271
1271
|
stdout: bool = typer.Option(
|
|
1272
1272
|
False, "--stdout", help="Print to stdout instead of writing a file."
|
|
1273
1273
|
),
|
|
1274
|
-
|
|
1275
|
-
False, "--
|
|
1274
|
+
exclude_done: bool = typer.Option(
|
|
1275
|
+
False, "--exclude-done", help="Exclude Done/archived epics from the roadmap."
|
|
1276
1276
|
),
|
|
1277
1277
|
) -> None:
|
|
1278
1278
|
"""Generate ROADMAP.md — version-controlled Markdown + Mermaid source of truth.
|
|
@@ -1280,10 +1280,14 @@ def roadmap_export(
|
|
|
1280
1280
|
Renders epics, spec progress, ADRs, and active bullets into a Mermaid-enhanced
|
|
1281
1281
|
Markdown document. Safe to commit alongside beacon.md; regenerate on demand or
|
|
1282
1282
|
wire into CI with ``beacon roadmap export``.
|
|
1283
|
+
|
|
1284
|
+
Done/archived epics are included by default (up to ``roadmap_done_limit`` in
|
|
1285
|
+
your manifest, defaulting to 3). Pass ``--exclude-done`` to suppress them.
|
|
1283
1286
|
"""
|
|
1284
1287
|
from datetime import date
|
|
1285
1288
|
|
|
1286
1289
|
from beacon import roadmap as _roadmap
|
|
1290
|
+
from beacon.manifest import Manifest
|
|
1287
1291
|
|
|
1288
1292
|
root = _resolve_root(here, path)
|
|
1289
1293
|
if not (root / "project-management").is_dir():
|
|
@@ -1293,9 +1297,11 @@ def roadmap_export(
|
|
|
1293
1297
|
"[dim]beacon roadmap export /path/to/project[/dim]"
|
|
1294
1298
|
)
|
|
1295
1299
|
raise typer.Exit(1)
|
|
1300
|
+
_m = Manifest.load(root)
|
|
1301
|
+
done_limit = 0 if exclude_done else (_m.roadmap_done_limit if _m else 3)
|
|
1296
1302
|
today = date.today().isoformat()
|
|
1297
1303
|
data = _roadmap.collect(root)
|
|
1298
|
-
content = _roadmap.render_markdown(data, today,
|
|
1304
|
+
content = _roadmap.render_markdown(data, today, done_limit=done_limit)
|
|
1299
1305
|
if stdout:
|
|
1300
1306
|
console.print(content)
|
|
1301
1307
|
return
|
|
@@ -1303,13 +1309,13 @@ def roadmap_export(
|
|
|
1303
1309
|
dest.write_text(content, encoding="utf-8")
|
|
1304
1310
|
console.print(f"[green]✓[/green] Roadmap exported → [cyan]{dest.relative_to(root)}[/cyan]")
|
|
1305
1311
|
if not data.epics:
|
|
1306
|
-
if data.archived_epics and
|
|
1312
|
+
if data.archived_epics and exclude_done:
|
|
1307
1313
|
n = len(data.archived_epics)
|
|
1308
1314
|
plural = "s" if n > 1 else ""
|
|
1309
1315
|
console.print(
|
|
1310
1316
|
f"[dim] ({n} archived epic{plural}"
|
|
1311
|
-
" —
|
|
1312
|
-
"[/dim cyan][dim] to include completed work)[/dim]"
|
|
1317
|
+
" — remove [/dim][dim cyan]--exclude-done"
|
|
1318
|
+
"[/dim cyan][dim] to include recent completed work)[/dim]"
|
|
1313
1319
|
)
|
|
1314
1320
|
elif not data.archived_epics:
|
|
1315
1321
|
console.print(
|
|
@@ -1325,6 +1331,9 @@ def roadmap_render(
|
|
|
1325
1331
|
output: Path | None = typer.Option(
|
|
1326
1332
|
None, "--output", "-o", help="Output path (default: ROADMAP.html in project root)."
|
|
1327
1333
|
),
|
|
1334
|
+
exclude_done: bool = typer.Option(
|
|
1335
|
+
False, "--exclude-done", help="Exclude Done/archived epics from the visualization."
|
|
1336
|
+
),
|
|
1328
1337
|
) -> None:
|
|
1329
1338
|
"""Generate ROADMAP.html — Structural Breath interactive visualization (gitignored).
|
|
1330
1339
|
|
|
@@ -1332,10 +1341,14 @@ def roadmap_render(
|
|
|
1332
1341
|
cards, active-bullet feed, and ADR index — all styled with the Structural Breath
|
|
1333
1342
|
design system (dark, blueprint-grid, engineering-whitepaper aesthetic). Open
|
|
1334
1343
|
directly in a browser, screenshot into a slide deck, or host as a static page.
|
|
1344
|
+
|
|
1345
|
+
Done/archived epics are included by default (up to ``roadmap_done_limit`` in
|
|
1346
|
+
your manifest, defaulting to 3). Pass ``--exclude-done`` to suppress them.
|
|
1335
1347
|
"""
|
|
1336
1348
|
from datetime import date
|
|
1337
1349
|
|
|
1338
1350
|
from beacon import roadmap as _roadmap
|
|
1351
|
+
from beacon.manifest import Manifest
|
|
1339
1352
|
|
|
1340
1353
|
root = _resolve_root(here, path)
|
|
1341
1354
|
if not (root / "project-management").is_dir():
|
|
@@ -1345,9 +1358,11 @@ def roadmap_render(
|
|
|
1345
1358
|
"[dim]beacon roadmap render /path/to/project[/dim]"
|
|
1346
1359
|
)
|
|
1347
1360
|
raise typer.Exit(1)
|
|
1361
|
+
_m = Manifest.load(root)
|
|
1362
|
+
done_limit = 0 if exclude_done else (_m.roadmap_done_limit if _m else 3)
|
|
1348
1363
|
today = date.today().isoformat()
|
|
1349
1364
|
data = _roadmap.collect(root)
|
|
1350
|
-
content = _roadmap.render_html(data, today)
|
|
1365
|
+
content = _roadmap.render_html(data, today, done_limit=done_limit)
|
|
1351
1366
|
dest = output or (root / "ROADMAP.html")
|
|
1352
1367
|
dest.write_text(content, encoding="utf-8")
|
|
1353
1368
|
console.print(f"[green]✓[/green] Roadmap rendered → [cyan]{dest.relative_to(root)}[/cyan]")
|
|
@@ -50,6 +50,11 @@ class Manifest:
|
|
|
50
50
|
# `--no-speckit` / declining the offer sets this False; pre-PR installs
|
|
51
51
|
# without the field default False (no nag for users who never opted in).
|
|
52
52
|
speckit_requested: bool = False
|
|
53
|
+
# How many of the most-recently-completed (archived) epics to include in
|
|
54
|
+
# roadmap output by default. 0 = exclude Done epics entirely; any positive
|
|
55
|
+
# integer caps the count. Use ``--exclude-done`` on the CLI to override to
|
|
56
|
+
# 0 for a single run without touching this value.
|
|
57
|
+
roadmap_done_limit: int = 3
|
|
53
58
|
|
|
54
59
|
@classmethod
|
|
55
60
|
def fresh(cls) -> Manifest:
|
|
@@ -71,6 +76,7 @@ class Manifest:
|
|
|
71
76
|
hooks_enabled=bool(data.get("hooks_enabled", True)),
|
|
72
77
|
git_flow=str(data.get("git_flow", "trunk")),
|
|
73
78
|
speckit_requested=bool(data.get("speckit_requested", False)),
|
|
79
|
+
roadmap_done_limit=int(data.get("roadmap_done_limit", 3)),
|
|
74
80
|
)
|
|
75
81
|
|
|
76
82
|
def save(self, project_root: Path) -> Path:
|
|
@@ -17,6 +17,8 @@ Run:
|
|
|
17
17
|
beacon roadmap export
|
|
18
18
|
```
|
|
19
19
|
|
|
20
|
+
This includes the most-recently-completed epics by default (controlled by `roadmap_done_limit` in the manifest, defaulting to 3). Pass `--exclude-done` to suppress Done/archived epics.
|
|
21
|
+
|
|
20
22
|
If the user passed `render` as an argument (i.e. `$ARGUMENTS` contains the word `render`), also run:
|
|
21
23
|
```bash
|
|
22
24
|
beacon roadmap render
|
|
@@ -26,7 +28,7 @@ beacon roadmap render
|
|
|
26
28
|
|
|
27
29
|
Read the just-written `ROADMAP.md` and report concisely:
|
|
28
30
|
|
|
29
|
-
- **Epic counts** by status: Active / Planning / Paused / Done
|
|
31
|
+
- **Epic counts** by status: Active / Planning / Paused / Done (including any archived epics shown)
|
|
30
32
|
- **Fidelity** for each epic — show the badge (`S+/S? A+/A? T:N%`) and flag any that are `S?` (no specs) or `A?` (no ADRs)
|
|
31
33
|
- **In-flight bullets** — how many worktrees have active bullets and which epics they're attached to
|
|
32
34
|
- **Roadmap coverage** — fraction of Active epics that have both specs and ADRs filled in
|
|
@@ -208,6 +208,15 @@ def _parse_adr(root: Path, adr_path: str) -> AdrSummary:
|
|
|
208
208
|
return AdrSummary(path=adr_path, token=token, title=title, status=status)
|
|
209
209
|
|
|
210
210
|
|
|
211
|
+
def _select_done_epics(archived: list[Epic], done_limit: int) -> list[Epic]:
|
|
212
|
+
"""Return the N most-recently-started archived epics, sorted chronologically."""
|
|
213
|
+
if done_limit <= 0:
|
|
214
|
+
return []
|
|
215
|
+
by_recency = sorted(archived, key=lambda e: e.started or "0000-00-00", reverse=True)
|
|
216
|
+
selected = by_recency[:done_limit]
|
|
217
|
+
return sorted(selected, key=lambda e: e.started or "9999-99-99")
|
|
218
|
+
|
|
219
|
+
|
|
211
220
|
def _mermaid_gantt_src(
|
|
212
221
|
epics: list[Epic],
|
|
213
222
|
rollups: dict[str, Rollup],
|
|
@@ -290,12 +299,13 @@ def _markdown_status_table(
|
|
|
290
299
|
return "\n".join(rows)
|
|
291
300
|
|
|
292
301
|
|
|
293
|
-
def _to_json_data(data: RoadmapData, generated_at: str, *,
|
|
302
|
+
def _to_json_data(data: RoadmapData, generated_at: str, *, done_limit: int = 3) -> dict:
|
|
294
303
|
"""Serialise RoadmapData to the shape embedded in ROADMAP.html."""
|
|
295
|
-
|
|
304
|
+
done_epics = _select_done_epics(data.archived_epics, done_limit)
|
|
305
|
+
all_epics = data.epics + done_epics
|
|
296
306
|
epics_list = []
|
|
297
307
|
for e in all_epics:
|
|
298
|
-
if
|
|
308
|
+
if done_limit == 0 and e.status == "Done":
|
|
299
309
|
continue
|
|
300
310
|
roll = data.rollups.get(e.slug)
|
|
301
311
|
f = data.fidelity.get(e.slug)
|
|
@@ -354,7 +364,7 @@ def _to_json_data(data: RoadmapData, generated_at: str, *, include_done: bool =
|
|
|
354
364
|
# Build gantt_bars for D3
|
|
355
365
|
gantt_bars = []
|
|
356
366
|
for e in all_epics:
|
|
357
|
-
if
|
|
367
|
+
if done_limit == 0 and e.status == "Done":
|
|
358
368
|
continue
|
|
359
369
|
if not e.started:
|
|
360
370
|
continue
|
|
@@ -452,7 +462,7 @@ def render_markdown(
|
|
|
452
462
|
data: RoadmapData,
|
|
453
463
|
generated_at: str,
|
|
454
464
|
*,
|
|
455
|
-
|
|
465
|
+
done_limit: int = 3,
|
|
456
466
|
) -> str:
|
|
457
467
|
"""Render ROADMAP.md content from collected data."""
|
|
458
468
|
lines: list[str] = []
|
|
@@ -465,7 +475,8 @@ def render_markdown(
|
|
|
465
475
|
lines.append(f"> {data.vision_excerpt}")
|
|
466
476
|
lines.append("")
|
|
467
477
|
|
|
468
|
-
|
|
478
|
+
done_epics = _select_done_epics(data.archived_epics, done_limit)
|
|
479
|
+
visible_epics = data.epics + done_epics
|
|
469
480
|
|
|
470
481
|
if not visible_epics:
|
|
471
482
|
if data.archived_epics:
|
|
@@ -473,7 +484,8 @@ def render_markdown(
|
|
|
473
484
|
plural = "s" if n > 1 else ""
|
|
474
485
|
lines.append(
|
|
475
486
|
f"_No active epics — {n} epic{plural} archived. "
|
|
476
|
-
|
|
487
|
+
"Remove `--exclude-done` or raise `roadmap_done_limit` in your manifest"
|
|
488
|
+
" to include completed work._"
|
|
477
489
|
)
|
|
478
490
|
else:
|
|
479
491
|
lines.append(
|
|
@@ -497,7 +509,7 @@ def render_markdown(
|
|
|
497
509
|
lines.append("")
|
|
498
510
|
lines.append("```mermaid")
|
|
499
511
|
lines.append(
|
|
500
|
-
_mermaid_gantt_src(visible_epics, data.rollups, generated_at, include_done=
|
|
512
|
+
_mermaid_gantt_src(visible_epics, data.rollups, generated_at, include_done=(done_limit > 0))
|
|
501
513
|
)
|
|
502
514
|
lines.append("```")
|
|
503
515
|
lines.append("")
|
|
@@ -545,7 +557,7 @@ def render_markdown(
|
|
|
545
557
|
return "\n".join(lines)
|
|
546
558
|
|
|
547
559
|
|
|
548
|
-
def render_html(data: RoadmapData, generated_at: str) -> str:
|
|
560
|
+
def render_html(data: RoadmapData, generated_at: str, *, done_limit: int = 3) -> str:
|
|
549
561
|
"""Render ROADMAP.html by injecting JSON into the Structural Breath template."""
|
|
550
562
|
from importlib import resources as _res
|
|
551
563
|
|
|
@@ -554,7 +566,7 @@ def render_html(data: RoadmapData, generated_at: str) -> str:
|
|
|
554
566
|
)
|
|
555
567
|
template = template_bytes.decode("utf-8")
|
|
556
568
|
|
|
557
|
-
json_data = _to_json_data(data, generated_at)
|
|
569
|
+
json_data = _to_json_data(data, generated_at, done_limit=done_limit)
|
|
558
570
|
# Use json.dumps with separators for compact embedding; escape </script> sequences
|
|
559
571
|
json_str = json.dumps(json_data, ensure_ascii=False).replace("</script>", "<\\/script>")
|
|
560
572
|
|
|
@@ -568,26 +580,36 @@ def generate_markdown(
|
|
|
568
580
|
root: Path,
|
|
569
581
|
output: Path | None = None,
|
|
570
582
|
*,
|
|
571
|
-
|
|
583
|
+
done_limit: int | None = None,
|
|
572
584
|
) -> Path:
|
|
573
585
|
"""Collect data, render, and write ROADMAP.md. Returns the written path."""
|
|
574
586
|
from datetime import date
|
|
575
587
|
|
|
588
|
+
from beacon.manifest import Manifest
|
|
589
|
+
|
|
590
|
+
if done_limit is None:
|
|
591
|
+
m = Manifest.load(root)
|
|
592
|
+
done_limit = m.roadmap_done_limit if m else 3
|
|
576
593
|
today = date.today().isoformat()
|
|
577
594
|
data = collect(root)
|
|
578
|
-
content = render_markdown(data, today,
|
|
595
|
+
content = render_markdown(data, today, done_limit=done_limit)
|
|
579
596
|
dest = output or (root / "ROADMAP.md")
|
|
580
597
|
dest.write_text(content, encoding="utf-8")
|
|
581
598
|
return dest
|
|
582
599
|
|
|
583
600
|
|
|
584
|
-
def generate_html(root: Path, output: Path | None = None) -> Path:
|
|
601
|
+
def generate_html(root: Path, output: Path | None = None, *, done_limit: int | None = None) -> Path:
|
|
585
602
|
"""Collect data, render, and write ROADMAP.html. Returns the written path."""
|
|
586
603
|
from datetime import date
|
|
587
604
|
|
|
605
|
+
from beacon.manifest import Manifest
|
|
606
|
+
|
|
607
|
+
if done_limit is None:
|
|
608
|
+
m = Manifest.load(root)
|
|
609
|
+
done_limit = m.roadmap_done_limit if m else 3
|
|
588
610
|
today = date.today().isoformat()
|
|
589
611
|
data = collect(root)
|
|
590
|
-
content = render_html(data, today)
|
|
612
|
+
content = render_html(data, today, done_limit=done_limit)
|
|
591
613
|
dest = output or (root / "ROADMAP.html")
|
|
592
614
|
dest.write_text(content, encoding="utf-8")
|
|
593
615
|
return dest
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/resources/languages/python.toml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/resources/roadmap_template.html
RENAMED
|
File without changes
|
{beacon_framework-1.2.2 → beacon_framework-1.3.0}/src/beacon/resources/user-facing-docs/README.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|