@dzhechkov/skills-feature-adr 1.3.32 → 1.3.34

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dzhechkov/skills-feature-adr",
3
- "version": "1.3.32",
3
+ "version": "1.3.34",
4
4
  "description": "Adaptive Feature Development skill pack for Claude Code — 11-step pipeline with Complexity Router (S/M/L/XL), ADR-driven architecture, 15 agentic-qe skills, multi-agent fleet QE. Supports --full-qe, --full-qe-extended, --with-learning, and --knowledge-extractor modes.",
5
5
  "bin": {
6
6
  "skills-feature-adr": "./bin/cli.js"
@@ -36,11 +36,20 @@ async function run(options) {
36
36
  const templatesDir = getTemplatesDir();
37
37
 
38
38
  // ── b) Get installed components ───────────────────────────────────────
39
- const installedKeys = manifest.components || [];
40
- if (installedKeys.length === 0) {
39
+ const manifestKeys = manifest.components || [];
40
+ if (manifestKeys.length === 0) {
41
41
  warn('Manifest lists no installed components. Consider running init instead.');
42
42
  process.exit(1);
43
43
  }
44
+ // UNION the manifest's components with the CORE components the NEW template provides. A component
45
+ // ADDED upstream AFTER this install (e.g. `workflows`, bundled in a later release) would otherwise be
46
+ // invisible to `update` — never installed, and worse, a file it ships (`.claude/workflows/feature-adr.js`)
47
+ // could be mis-flagged as an orphan "dropped from template" and DELETED. Installing the union fixes
48
+ // both: new core components get added, and every file the current template provides stays in the
49
+ // rebuilt file-set, so it is updated (never orphaned). Optional components are only touched if they
50
+ // were already installed (they stay driven by the manifest).
51
+ const newCoreKeys = Object.keys(COMPONENTS).filter((k) => fileExists(path.join(templatesDir, COMPONENTS[k].src)));
52
+ const installedKeys = [...new Set([...manifestKeys, ...newCoreKeys])];
44
53
 
45
54
  info(`Current version: ${dim(manifest.version)}`);
46
55
  const pkgPath = path.resolve(__dirname, '../../package.json');
@@ -274,24 +283,25 @@ async function run(options) {
274
283
  }
275
284
 
276
285
  if (totalAdded === 0 && totalModified === 0 && orphans.length === 0) {
277
- if (keptModified.length > 0) {
278
- // Nothing to copy, but files were kept. Refresh the per-file baseline so a
279
- // legacy (no-hashes) install self-heals into the 3-way regime and a kept
280
- // conflict records the current template as its baseline (D3/D4). We do NOT
281
- // bump the version \u2014 no template bytes were actually applied. Never write
282
- // under --dry-run.
283
- if (!dryRun) {
284
- const { newHashes } = rebuildManifestData();
285
- if (Object.keys(newHashes).length > 0) {
286
- manifest.hashes = newHashes;
287
- manifest.updatedAt = new Date().toISOString();
288
- writeManifest(targetDir, manifest);
289
- }
286
+ // Nothing to copy, but the MANIFEST may still be stale: a component newly covered by the union
287
+ // (or a file the template ships that the old manifest never tracked) must be re-tracked so the
288
+ // manifest matches reality \u2014 otherwise a later `remove`/`update` mis-reasons about ownership. Also
289
+ // refreshes the per-file baseline so a legacy (no-hashes) install self-heals into the 3-way regime.
290
+ // Never bump the version (no template bytes applied) and never write under --dry-run.
291
+ if (!dryRun) {
292
+ const { allFiles, newHashes } = rebuildManifestData();
293
+ const prevFiles = JSON.stringify((manifest.files || []).map(toManifestPath).sort());
294
+ const nextFiles = JSON.stringify(allFiles.slice().sort());
295
+ const compsChanged = JSON.stringify((manifest.components || []).slice().sort()) !== JSON.stringify(installedKeys.slice().sort());
296
+ if (prevFiles !== nextFiles || compsChanged || Object.keys(newHashes).length > 0) {
297
+ manifest.files = allFiles.sort();
298
+ manifest.components = installedKeys;
299
+ if (Object.keys(newHashes).length > 0) manifest.hashes = newHashes;
300
+ manifest.updatedAt = new Date().toISOString();
301
+ writeManifest(targetDir, manifest);
290
302
  }
291
- success('No files to update \u2014 locally modified file(s) kept.');
292
- } else {
293
- success('Everything is up to date!');
294
303
  }
304
+ success(keptModified.length > 0 ? 'No files to update \u2014 locally modified file(s) kept.' : 'Everything is up to date!');
295
305
  process.exit(0);
296
306
  }
297
307