Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
132 changes: 132 additions & 0 deletions dev-docs/specs/2026-10-11-plcc-ng-demo-migration-design.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
# Migrating plcc-ng-demo's tracker into `ourPLCC/dev` — design

Date: 2026-10-11

## Problem

plcc-ng-demo keeps a small file-based tracker in `dev-docs/issues/`: five
issues, 001–005, all closed. The central tracker design
([2026-10-08-199-central-tracker-design.md](../../../plcc-ng/dev-docs/specs/2026-10-08-199-central-tracker-design.md),
"the central spec" below) says plcc-ng-demo is migrated "from this spec", but
leaves two things open:

- `migrate/` converts plcc-ng's tracker only. plcc-ng-demo's files use the
same format (a `**Type:**` line, closed issues in `done/`), but the plcc-ng
driver hard-codes plcc-ng's project, offset, and GitHub URL.
- Three demo issues were copied into plcc-ng by hand. The central spec's rule
for such duplicates names only languages-ng's.

This spec records only what plcc-ng-demo adds to the central spec and to the
[languages-ng migration spec](2026-10-11-languages-ng-migration-design.md).
Everything those specs say about the migration and do not override here
applies.

## Supersedes

[2026-10-08-199-central-tracker-design.md](../../../plcc-ng/dev-docs/specs/2026-10-08-199-central-tracker-design.md),
for plcc-ng-demo only: "Duplicated upstream findings" (below lists the demo's).

## Decision summary

Add a plcc-ng-demo driver to `migrate/` that reuses plcc-ng's loader and
converter with the demo's project, offset (+800), and GitHub URL, and adds a
`duplicates` triage table in the shape languages-ng uses. Converting by hand is
not an option: the `backlog` CLI allocates IDs itself, so it cannot create
`CR-801`–`CR-805`, and the tracker files are not edited by hand.

No legacy number repeats, so no duplicate-number range is reserved.

The issues contain no Markdown links and no bare `#N`, so link rewriting has
nothing to do. The driver still runs it, so the report would show anything
missed.

## Triage

Recorded in `migrate/plcc-ng-demo-triage.json`: `open` is empty, and
`duplicates` maps legacy number → plcc-ng number.

**Duplicates of plcc-ng issues** become `Done` + `wontdo` in `completed/`,
with project `plcc-ng`, the type of the plcc-ng CR they duplicate, and the
final summary `Duplicate of CR-<n>, filed upstream by hand.`

| plcc-ng-demo | CR | plcc-ng | type |
| --- | --- | --- | --- |
| 001 | CR-801 | CR-159 | docs |
| 002 | CR-802 | CR-160 | fix |
| 005 | CR-805 | CR-161 | feat |

CR-160 and CR-161 already cite CR-802 and CR-805 as where they were first
filed, so those IDs must exist.

**Demo-local issues** become `Done` in `completed/`, project `plcc-ng-demo`,
type from the legacy `**Type:**`:

| plcc-ng-demo | CR | type |
| --- | --- | --- |
| 003 | CR-803 | docs |
| 004 | CR-804 | chore |

**Expected counts:** `completed/` 5, `tasks/` 0, `drafts/` 0.

## Switch-over in plcc-ng-demo

**Devcontainer.** Set up as plcc-ng's (already done: the `../dev` clone and
mount, `BACKLOG_CWD`, `safe.directory`, the `plcc-ng-demo-claude` volume,
the pinned `backlog`, and `bin/install/claude-imports.bash`).

**`AGENTS.md`** imports `../dev/ORG-AGENTS.md`, `../dev/CONTRIBUTING.md`,
then `CONTRIBUTING.md`, one per line. It has no repo-specific agent rules yet,
so it has no section for them.

**`CONTRIBUTING.md`** (new) opens with the link to the org developer guide,
then:

- "Where this repo differs": nowhere; the existing
`dev-docs/plans/2026-07-21-plcc-ng-demo.md` is a kept plan, frozen as
history, with none added.
- Development environment: the `../dev` clone and mount, the tracker
`project` value `plcc-ng-demo`, old numbers at +800 (`#3` is `CR-803`), and
why the container approves `AGENTS.md`'s imports and how to check
(`/memory`), as plcc-ng's says.
- Commands: `bin/install/claude-imports.bash`.

**Retire the old tracker.** Delete `dev-docs/issues/`, `bin/issues/`, and
`dev-docs/roadmap.md` (it holds only the old tracker's empty "Open Issues"
list). Allow `Bash(backlog:*)` in `.claude/settings.json`.

**Frozen documents** (`dev-docs/specs/`, `dev-docs/plans/`) mention
`dev-docs/issues/` and `bin/issues/` only as plain text, so they are not
edited.

## Order

1. `migrate/` gains the plcc-ng-demo driver, with tests, on its own branch in
this repo.
2. Dry run from plcc-ng-demo `main` into a scratch copy of the tracker; a
human reviews the report.
3. The plcc-ng-demo switch-over branch is prepared.
4. The conversion re-runs from plcc-ng-demo `main` (the freeze point) and
lands in the tracker.
5. Human checkpoint before merging the plcc-ng-demo branch: rebuild from it
on the host; the container starts, `backlog task list` works, and
`/memory` lists the imported files. From this point no issue is filed in
`dev-docs/issues/`.

## Verification

- `migrate/tests` cover the new driver and the `duplicates` table; the
plcc-ng and languages-ng tests still pass.
- `verify.py` for plcc-ng-demo: per-folder counts match the expected counts
above; `backlog task view` succeeds for 801–805; `backlog doctor` and
`bin/check.py` are clean.
- In plcc-ng-demo after switch-over, `grep -rn 'dev-docs/issues\|bin/issues\|roadmap'`
finds nothing outside `.git` and the frozen `dev-docs/plans/` and
`dev-docs/specs/`, and no relative Markdown link points at a deleted file.

## Rejected alternatives

| Alternative | Why not |
| --- | --- |
| Duplicates as plain `Done` in project `plcc-ng-demo` | They were closed before the move, but the languages-ng rule already settles hand-copied upstream findings; one rule for both repos |
| Generalize `plcc_ng.py` in place with command-line options | A driver per repo is how `drivers.py`, `verify`, and `citations` already select behavior |
| Skip the spec and record the decisions in the CRs | Specs hold decisions and CRs reference them; the duplicate rule overrides the central spec, which belongs in a spec |
17 changes: 11 additions & 6 deletions dev-docs/tracker.md
Original file line number Diff line number Diff line change
Expand Up @@ -192,15 +192,20 @@ the project and type rules.
## Migration tooling

`migrate/` converts legacy in-repo trackers (Python 3 standard library), with
one driver per repo: `python3 -m migrate.plcc_ng` and
`python3 -m migrate.languages_ng` (each takes `--repo`, `--tracker`,
`--triage`, `--report`). `python3 -m migrate.verify` and
`python3 -m migrate.citations` take `--driver plcc-ng|languages-ng` (default
`plcc-ng`); `python3 -m migrate.repo_links --project <repo>` picks the driver
from the project. Decisions are in `migrate/<repo>-triage.json`, results in
one driver per repo: `python3 -m migrate.plcc_ng`,
`python3 -m migrate.languages_ng`, and `python3 -m migrate.plcc_ng_demo`
(each takes `--repo`, `--tracker`, `--triage`, `--report`).
`python3 -m migrate.verify` and `python3 -m migrate.citations` take
`--driver plcc-ng|languages-ng|plcc-ng-demo` (default `plcc-ng`);
`python3 -m migrate.repo_links --project <repo>` picks the driver from the
project. Decisions are in `migrate/<repo>-triage.json`, results in
`migrate/reports/<repo>.md`. plcc-ng's triage keys (`open`,
`type_overrides`) are a legacy number (`"105"`) or, for a number two files
share, the file stem (`"035-python-emitter-missing-semantics-blocks"`).
plcc-ng-demo's tracker has plcc-ng's format, so its driver runs plcc-ng's
converter at offset +800; its triage file adds `duplicates` (legacy number →
the plcc-ng CR it duplicates), per
[its migration spec](specs/2026-10-11-plcc-ng-demo-migration-design.md).
languages-ng's are legacy numbers only, and its triage file adds
`duplicates` (legacy number → the plcc-ng CR it duplicates), `references`
(legacy number → `{"#N": replacement}` for a bare `#N` the tool cannot
Expand Down
2 changes: 1 addition & 1 deletion migrate/citations.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""Count citations of each open legacy issue, as triage evidence.

Usage: python3 -m migrate.citations --repo REPO [--driver plcc-ng|languages-ng]
Usage: python3 -m migrate.citations --repo REPO [--driver plcc-ng|languages-ng|plcc-ng-demo]
"""
import argparse
import re
Expand Down
3 changes: 2 additions & 1 deletion migrate/drivers.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
"""The legacy-tracker drivers, one per migrated repo, by project name."""
import importlib

DRIVERS = {"plcc-ng": "migrate.plcc_ng", "languages-ng": "migrate.languages_ng"}
DRIVERS = {"plcc-ng": "migrate.plcc_ng", "languages-ng": "migrate.languages_ng",
"plcc-ng-demo": "migrate.plcc_ng_demo"}


def load(project):
Expand Down
11 changes: 11 additions & 0 deletions migrate/emit.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
"""Render Backlog.md task files from legacy issues."""
import re
from pathlib import Path

CORE_TYPES = ("fix", "feat", "docs", "test", "refactor", "chore")
TYPE_MAP = {"bug": "fix", "enhancement": "feat", "feature": "feat", "perf": "fix",
**{t: t for t in CORE_TYPES}}
WONTDO_RE = re.compile(r"^(abandoned|superseded)\b", re.IGNORECASE)
HEADING_RE = re.compile(r"^#{1,5} ")
TYPE_LINE_RE = re.compile(r"^type: (\S+)$", re.MULTILINE)


def yaml_quote(s):
Expand Down Expand Up @@ -68,3 +70,12 @@ def render_task(*, task_id, title, status, created, labels, description,
if final_summary:
text += "\n" + _section("Final Summary", "FINAL_SUMMARY", final_summary.strip())
return text


def tracker_type(backlog, cr):
"""The type of CR-<cr> in the tracker, or None if the tracker has no such CR."""
for folder in ("tasks", "completed"):
for path in (Path(backlog) / folder).glob(f"cr-{cr} - *.md"):
found = TYPE_LINE_RE.search(path.read_text(encoding="utf-8"))
return found.group(1) if found else None
return None
13 changes: 2 additions & 11 deletions migrate/languages_ng.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
import sys
from pathlib import Path

from migrate.emit import CORE_TYPES, TYPE_MAP, assemble_description, filename_for, render_task
from migrate.emit import (CORE_TYPES, TYPE_MAP, assemble_description, filename_for,
render_task, tracker_type)
from migrate.legacy import parse_frontmatter_issue
from migrate.links import IssueRef, LinkContext, rewrite_issue_body

Expand All @@ -24,7 +25,6 @@
FOLDERS = ("tasks", "completed", "drafts")
AS_FOLDER = {"cr": "tasks", "draft": "drafts", "wontdo": "completed"}
TRIAGE_TABLES = ("open", "duplicates", "type_overrides", "references")
TYPE_LINE_RE = re.compile(r"^type: (\S+)$", re.MULTILINE)
DRAFT_FILE_RE = re.compile(r"^draft-(\d+) - ")


Expand Down Expand Up @@ -52,15 +52,6 @@ def expected_counts(issues, triage):
return counts


def tracker_type(backlog, cr):
"""The type of CR-<cr> in the tracker, or None if the tracker has no such CR."""
for folder in ("tasks", "completed"):
for path in (Path(backlog) / folder).glob(f"cr-{cr} - *.md"):
found = TYPE_LINE_RE.search(path.read_text(encoding="utf-8"))
return found.group(1) if found else None
return None


def validate(issues, triage, backlog):
"""Return {legacy number: type} for the duplicates; exit listing every problem instead."""
errors, dup_types = [], {}
Expand Down
8 changes: 8 additions & 0 deletions migrate/plcc-ng-demo-triage.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"open": {},
"duplicates": {
"1": 159,
"2": 160,
"5": 161
}
}
Loading
Loading