Skip to content

T-5PLQ-regen-walks-skill-co-located-scripts

Status: closed/done · Impact: medium · Complexity: small

Auto-generated from a /sdlc:task-work post-mortem. Review and promote to open/ready before picking up.

T-UBJK-co-locate-skill-specific-scripts moved setup_planning.py, new_epic.py, and migrate_entities.py from plugin/scripts/ into their owning skill directory. site/scripts/regen.mjs only walks plugin/scripts/ when generating the script reference section, so those three scripts no longer have auto-generated reference pages. Close the gap so the co-location principle (“co-locate first, promote when shared”) doesn’t silently undercover the site reference.

site/scripts/regen.mjs defines regenScripts() which iterates listFiles(join(PLUGIN_DIR, 'scripts'), n => n.endsWith('.py')). There is no second walk over plugin/skills/<skill>/*.py. After the co-location move landed, the three pages under site/src/content/docs/reference/scripts/{setup_planning,new_epic,migrate_entities}.md were removed because their source paths no longer exist where regen looks.

Regen produces a script reference page for every .py file in plugin/scripts/ AND for every .py file that sits next to a SKILL.md under plugin/skills/<name>/. Output paths and frontmatter stay one-per-script under site/src/content/docs/reference/scripts/; duplicate stem names (vanishingly unlikely given the co-location rule) are resolved by namespacing the destination filename (<skill>-<script>.md) or by erroring loudly.

  1. Extend regenScripts() in site/scripts/regen.mjs: collect a second batch of script paths by iterating listDirs(SKILLS_DIR) and for each skill dir, listFiles(skillDir, n => n.endsWith('.py')).
  2. Destination filename: keep flat <stem>.md under site/src/content/docs/reference/scripts/. If two scripts share a stem across plugin/scripts/ and any skill dir, error loudly (no collisions exist today; the co-location rule keeps stems unique per ownership). Namespaced <skill>-<stem>.md is rejected for now — it would change already-shipped page URLs for the three co-located scripts’ eventual restoration.
  3. Update the source-path string in the generated frontmatter so it points at the actual plugin/skills/<skill>/<script>.py location.
  4. Run regen against the current tree, verify the three reference pages reappear under their new source paths, verify no other reference page changed.
  • site/scripts/regen.mjs — extend regenScripts() to walk skill dirs in addition to plugin/scripts/.
  • AC-1: Running site/scripts/regen.mjs against a tree where plugin/skills/setup/setup_planning.py exists generates site/src/content/docs/reference/scripts/setup_planning.md with the source-path frontmatter pointing at plugin/skills/setup/setup_planning.py.
  • AC-2: All three previously-deleted reference pages (for setup_planning, new_epic, migrate_entities) are restored.
  • AC-3: Running regen twice produces zero git diff (idempotent).
  • AC-4: No prior plugin/scripts/*.py reference page changes content as a side effect of this change.
  • Auto-regenerating the page index/sidebar. The site’s existing Starlight machinery picks up new pages without sidebar changes; if it doesn’t, that’s a separate bug.
  • Walking arbitrary nesting under skill dirs. Only direct children of plugin/skills/<skill>/ are scanned, not plugin/skills/<skill>/scripts/ or any future subdir.
  • Namespacing the destination filename. Rejected for now to avoid changing URLs for the three about-to-be-restored pages.
  • none

Spawned by /sdlc:task-work post-mortem of T-UBJK-co-locate-skill-specific-scripts on 2026-05-20.

Captured by /sdlc:task-work on 2026-05-21. PR: pending.

  • AC-1: agent-manual — ran node site/scripts/regen.mjs against the worktree; confirmed site/src/content/docs/reference/scripts/setup_planning.md was created with _Generated from \plugin/skills/setup/setup_planning.py`._` and the matching AUTO-GENERATED marker.
  • AC-2: agent-manual — all three previously-deleted pages (setup_planning.md, new_epic.md, migrate_entities.md) appear under site/src/content/docs/reference/scripts/ after regen.
  • AC-3: agent-manual — ran regen twice; second run reported zero new changes (status diff between runs was empty for the script pages this task owns).
  • AC-4: agent-manual — diffed the worktree against the baseline (unmodified) regen run; the only NEW files my change introduces are the six co-located script pages. Pre-existing drift in site/src/content/docs/reference/{skills,entities}/ and in the plugin/scripts/* reference pages was present before this change and is unrelated — it stems from the regen output being stale relative to the plugin source.
  • The existing regenScripts() already separated “collect script paths” from “render and write,” so extending it to a second source root was a tight, local diff.
  • listDirs/listFiles helpers were already in place — no new filesystem traversal code needed.
  • start_task.py’s rebase phase surfaced the frontmatter conflict cleanly with a precise exit code; resolution was trivial because the conflict was purely a stamp-vs-stamp choice on the same field.
  • start_task.py rebase conflict on resumed runs — when a prior /sdlc:task-work run lands the readiness stamp on the feat branch but bails before Step 5b, the next run’s start-commit on main carries a different readiness_verified_at value (whichever stamp landed first on main vs the freshest one on the feat branch), producing a trivial rebase conflict on the task file. Resolution is mechanical (keep the newer stamp + main’s status edit) but the skill currently says “do not auto-resolve, surface to the user.” A targeted carve-out — “if the conflict is bounded to readiness_verified_at and/or last_reviewed on a single task file, auto-resolve by taking the freshest stamp” — would remove a human-in-the-loop step from resumed runs. → T-H0W9-task-work-rebase-frontmatter-conflict
  • Pre-existing regen drift bled into this PR’s scope analysis — running regen.mjs from a worktree branched off main produced ~12 unrelated M/?? entries (stale skill/entity pages, missing plugin/scripts/* pages) that had nothing to do with this task. Sorting feature output from drift required a baseline-regen comparison, which is manual judgement. A regen.mjs --check mode (or a CI gate that fails on any uncommitted regen output on main) would eliminate this whole class of friction by keeping the regen output continuously in sync. → T-ETML-decouple-regen-from-task-work-prs

← Back to Tasks