businesslens 0.12.0 → 0.13.0

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/CHANGELOG.md CHANGED
@@ -5,6 +5,16 @@ All notable changes to this project are documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [Unreleased]
9
+
10
+ ## [0.13.0] - 2026-09-12
11
+
12
+ ### Removed
13
+
14
+ - Hidden historical CLI options and command migration messages. Use the commands
15
+ and options shown in help, including `--cwd` and `--scope project|global`.
16
+ - One-off cleanup of old bare-name skills and Claude commands during installation.
17
+
8
18
  ## [0.12.0] - 2026-09-10
9
19
 
10
20
  ### Changed
package/dist/cli.js CHANGED
@@ -4,7 +4,7 @@ import { MAX_PRODUCT_LOGO_BYTES, PRODUCT_LOGO_FILENAME, validateProductLogo } fr
4
4
  import { reportDigest } from "./report-digest-BtjFf-4A.js";
5
5
  import { createRequire } from "node:module";
6
6
  import { basename, dirname, extname, isAbsolute, join, relative, resolve, sep } from "node:path";
7
- import { Command, CommanderError, Help, InvalidArgumentError, Option } from "commander";
7
+ import { Command, CommanderError, Help, InvalidArgumentError } from "commander";
8
8
  import { execFileSync, spawn, spawnSync } from "node:child_process";
9
9
  import { closeSync, constants, cpSync, existsSync, lstatSync, mkdirSync, mkdtempSync, openSync, readFileSync, readdirSync, realpathSync, renameSync, rmSync, rmdirSync, watch, writeFileSync } from "node:fs";
10
10
  import { createInterface } from "node:readline/promises";
@@ -3887,25 +3887,6 @@ const BUSINESSLENS_SKILLS = [
3887
3887
  "businesslens-verify"
3888
3888
  ];
3889
3889
  const MANIFEST_FILE = ".businesslens-install.json";
3890
- const LEGACY_SKILLS = [
3891
- "businesslens-init",
3892
- "businesslens-sync",
3893
- "businesslens-deep-dive",
3894
- "businesslens-doctor",
3895
- "businesslens-contribute",
3896
- "businesslens-implement",
3897
- "businesslens-validate",
3898
- "businesslens-plan",
3899
- "businesslens-publish",
3900
- "map",
3901
- "sync",
3902
- "deep-dive",
3903
- "publish",
3904
- "analyze-repo",
3905
- "validate-report",
3906
- "submit-report",
3907
- "push-report"
3908
- ];
3909
3890
  function bundledSkillsDir() {
3910
3891
  const here = dirname(fileURLToPath(import.meta.url));
3911
3892
  for (const candidate of [
@@ -3919,9 +3900,6 @@ const SKILL_DIRECTORY_NAME = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
3919
3900
  function isSkillDirectoryName(name) {
3920
3901
  return typeof name === "string" && SKILL_DIRECTORY_NAME.test(name);
3921
3902
  }
3922
- function isBusinessLensSkillName(name) {
3923
- return name.startsWith("businesslens-") || LEGACY_SKILLS.includes(name);
3924
- }
3925
3903
  function ownedChildPath(skillsDir, name) {
3926
3904
  if (!isSkillDirectoryName(name)) return void 0;
3927
3905
  const target = resolve(skillsDir, name);
@@ -3957,36 +3935,6 @@ function assertInstallTargets(cwd, targets, options = {}) {
3957
3935
  assertSafeTargets(skillsDir, readManifest(skillsDir), Boolean(options.force));
3958
3936
  }
3959
3937
  }
3960
- function removeLegacySkills(skillsDir, existing) {
3961
- const removed = [];
3962
- for (const name of LEGACY_SKILLS) {
3963
- const target = ownedChildPath(skillsDir, name);
3964
- if (target === void 0) continue;
3965
- if (!existsSync(target) || !existing?.skills.includes(name)) continue;
3966
- rmSync(target, {
3967
- recursive: true,
3968
- force: true
3969
- });
3970
- removed.push(name);
3971
- }
3972
- return removed;
3973
- }
3974
- function removeLegacyCommands(cwd, target) {
3975
- if (target.scope !== "project" || target.provider.id !== "claude") return [];
3976
- const project = resolve(cwd);
3977
- const commandFile = join(project, ".claude", "commands", "businesslens", "init.md");
3978
- if (!existsSync(commandFile)) return [];
3979
- try {
3980
- const source = readFileSync(commandFile, "utf8");
3981
- if (!source.includes("BusinessLens") && !source.includes(".businesslens/")) return [];
3982
- } catch {
3983
- return [];
3984
- }
3985
- rmSync(commandFile, { force: true });
3986
- const commandDirectory = dirname(commandFile);
3987
- if (readdirSync(commandDirectory).length === 0) rmSync(commandDirectory, { recursive: true });
3988
- return [relative(project, commandFile)];
3989
- }
3990
3938
  function writeManifest(skillsDir, manifest) {
3991
3939
  const file = join(skillsDir, MANIFEST_FILE);
3992
3940
  const temporary = `${file}.${randomUUID()}.tmp`;
@@ -4026,14 +3974,12 @@ function installSkillsToTarget(cwd, target, version, options = {}) {
4026
3974
  mkdirSync(skillsDir, { recursive: true });
4027
3975
  const existing = readManifest(skillsDir);
4028
3976
  assertSafeTargets(skillsDir, existing, Boolean(options.force));
4029
- const staleSkills = (existing?.skills ?? []).filter((previous) => !BUSINESSLENS_SKILLS.includes(previous)).filter(isBusinessLensSkillName).map((previous) => ownedChildPath(skillsDir, previous)).filter((stale) => stale !== void 0 && existsSync(stale));
3977
+ const staleSkills = (existing?.skills ?? []).filter((previous) => !BUSINESSLENS_SKILLS.includes(previous)).filter((name) => name.startsWith("businesslens-")).map((previous) => ownedChildPath(skillsDir, previous)).filter((stale) => stale !== void 0 && existsSync(stale));
4030
3978
  for (const name of BUSINESSLENS_SKILLS) installSkill(sourceRoot, skillsDir, name);
4031
- const removedLegacySkills = removeLegacySkills(skillsDir, existing);
4032
3979
  for (const stale of staleSkills) if (existsSync(stale)) rmSync(stale, {
4033
3980
  recursive: true,
4034
3981
  force: true
4035
3982
  });
4036
- const removedLegacyCommands = removeLegacyCommands(cwd, target);
4037
3983
  const now = (/* @__PURE__ */ new Date()).toISOString();
4038
3984
  writeManifest(skillsDir, {
4039
3985
  schema: 1,
@@ -4047,9 +3993,7 @@ function installSkillsToTarget(cwd, target, version, options = {}) {
4047
3993
  });
4048
3994
  return {
4049
3995
  ...target,
4050
- skillsDir,
4051
- removedLegacySkills,
4052
- removedLegacyCommands
3996
+ skillsDir
4053
3997
  };
4054
3998
  }
4055
3999
  function findManagedInstallations(cwd, providers, scopes, home) {
@@ -4076,14 +4020,9 @@ function canPrompt(options) {
4076
4020
  return !options.yes && Boolean(process.stdin.isTTY && process.stdout.isTTY);
4077
4021
  }
4078
4022
  function resolveScope(options) {
4079
- const aliases = [options.project ? "project" : void 0, options.global || options.user ? "global" : void 0].filter(Boolean);
4080
- if (aliases.length > 1) throw new UsageError("Choose only one of --project, --global, or --user.");
4081
- const explicit = options.scope?.trim().toLowerCase();
4082
- if (explicit && explicit !== "project" && explicit !== "global" && explicit !== "user") throw new UsageError("--scope must be project or global.");
4083
- const normalized = explicit === "user" ? "global" : explicit;
4084
- const alias = aliases[0];
4085
- if (normalized && alias && normalized !== alias) throw new UsageError("--scope conflicts with the selected scope flag.");
4086
- return normalized || alias;
4023
+ const scope$1 = options.scope?.trim().toLowerCase();
4024
+ if (scope$1 && scope$1 !== "project" && scope$1 !== "global") throw new UsageError("--scope must be project or global.");
4025
+ return scope$1;
4087
4026
  }
4088
4027
  function printDetected(cwd) {
4089
4028
  const detected = detectProviders(cwd);
@@ -4186,10 +4125,6 @@ async function runInstall(cwd, options = {}) {
4186
4125
  const roots = results.map((result) => formatDisplayPath(dirname(result.skillsDir)));
4187
4126
  console.log(`Installed BusinessLens into: ${roots.join(", ")} (${scope$1}).`);
4188
4127
  console.log(`Installed skills: ${BUSINESSLENS_SKILLS.join(", ")}.`);
4189
- const removed = results.flatMap((result) => result.removedLegacySkills);
4190
- if (removed.length > 0) console.log(`Removed retired BusinessLens skills: ${[...new Set(removed)].join(", ")}.`);
4191
- const removedCommands = results.flatMap((result) => result.removedLegacyCommands);
4192
- if (removedCommands.length > 0) console.log(`Removed retired BusinessLens commands: ${[...new Set(removedCommands)].join(", ")}.`);
4193
4128
  return 0;
4194
4129
  } catch (error) {
4195
4130
  console.error(error.message);
@@ -4388,15 +4323,9 @@ async function runPull(cwd, name, options, dependencies = {}) {
4388
4323
  //#endregion
4389
4324
  //#region src/commands/update.ts
4390
4325
  function resolveScopes(options) {
4391
- const aliases = [options.project ? "project" : void 0, options.global || options.user ? "global" : void 0].filter(Boolean);
4392
- if (aliases.length > 1) throw new UsageError("Choose only one of --project, --global, or --user.");
4393
- if (!options.scope && aliases.length === 0) return ["project", "global"];
4394
- const normalized = options.scope?.trim().toLowerCase();
4395
- if (normalized && normalized !== "project" && normalized !== "global" && normalized !== "user") throw new UsageError("--scope must be project or global.");
4396
- const scope$1 = normalized === "user" ? "global" : normalized;
4397
- if (scope$1 && aliases[0] && scope$1 !== aliases[0]) throw new UsageError("--scope conflicts with the selected scope flag.");
4398
- if ((scope$1 || aliases[0]) === "project") return ["project"];
4399
- if ((scope$1 || aliases[0]) === "global") return ["global"];
4326
+ const scope$1 = options.scope?.trim().toLowerCase();
4327
+ if (!scope$1) return ["project", "global"];
4328
+ if (scope$1 === "project" || scope$1 === "global") return [scope$1];
4400
4329
  throw new UsageError("--scope must be project or global.");
4401
4330
  }
4402
4331
  async function runUpdate(cwd, options = {}) {
@@ -4844,8 +4773,8 @@ async function runView(cwd, options) {
4844
4773
  //#endregion
4845
4774
  //#region src/cli.ts
4846
4775
  function cwdFor(command) {
4847
- const { cwd, C: legacyCwd } = command.optsWithGlobals();
4848
- return resolve(process.cwd(), cwd || legacyCwd || ".");
4776
+ const { cwd } = command.optsWithGlobals();
4777
+ return resolve(process.cwd(), cwd || ".");
4849
4778
  }
4850
4779
  function scope(value) {
4851
4780
  const normalized = value.trim().toLowerCase();
@@ -4858,14 +4787,6 @@ function port(value) {
4858
4787
  if (parsed < 1 || parsed > 65535) throw new InvalidArgumentError("expected an integer from 1 to 65535");
4859
4788
  return parsed;
4860
4789
  }
4861
- function legacyScopeOptions(command) {
4862
- return command.addOption(new Option("--project").hideHelp()).addOption(new Option("--global").hideHelp()).addOption(new Option("--user").hideHelp());
4863
- }
4864
- function retiredCommand(program, name, replacement) {
4865
- program.command(`${name} [arguments...]`, { hidden: true }).allowUnknownOption(true).description(`Use businesslens ${replacement}`).action((_arguments, _options, command) => {
4866
- command.error(`error: \`businesslens ${name}\` has moved. Use \`businesslens ${replacement}\`.`);
4867
- });
4868
- }
4869
4790
  function commandsBeforeOptions(output) {
4870
4791
  const trailingNewline = output.endsWith("\n") ? "\n" : "";
4871
4792
  const sections = output.trimEnd().split(/\n{2,}/);
@@ -4877,17 +4798,17 @@ function commandsBeforeOptions(output) {
4877
4798
  return sections.join("\n\n") + trailingNewline;
4878
4799
  }
4879
4800
  function createProgram(setExitCode) {
4880
- const program = new Command().name("businesslens").description("Product-Driven Development for coding agents").usage("<command> [options]").option("-c, --cwd <path>", "Run from another directory").addOption(new Option("-C <path>").hideHelp().conflicts("cwd")).version(cliVersion(), "-V, --version", "Show the CLI version").helpOption("-h, --help", "Show help for command").helpCommand("help [command]", "Show help for command").showSuggestionAfterError().configureHelp({
4801
+ const program = new Command().name("businesslens").description("Product-Driven Development for coding agents").usage("<command> [options]").option("-c, --cwd <path>", "Run from another directory").version(cliVersion(), "-V, --version", "Show the CLI version").helpOption("-h, --help", "Show help for command").helpCommand("help [command]", "Show help for command").showSuggestionAfterError().configureHelp({
4881
4802
  showGlobalOptions: true,
4882
4803
  formatHelp(command, helper) {
4883
4804
  const output = Help.prototype.formatHelp.call(helper, command, helper);
4884
4805
  return command.parent ? output : commandsBeforeOptions(output);
4885
4806
  }
4886
4807
  }).exitOverride();
4887
- legacyScopeOptions(program.command("install").summary("Install BusinessLens skills").description("Install BusinessLens skills for detected AI harnesses.").option("--providers <list>", "Comma-separated providers: claude,codex,cursor,gemini,github").option("--scope <scope>", "Installation scope: project or global", scope).option("--yes", "Accept detected providers and default to project scope").option("--force", "Replace an unmarked colliding BusinessLens skill directory")).action(async (options, command) => {
4808
+ program.command("install").summary("Install BusinessLens skills").description("Install BusinessLens skills for detected AI harnesses.").option("--providers <list>", "Comma-separated providers: claude,codex,cursor,gemini,github").option("--scope <scope>", "Installation scope: project or global", scope).option("--yes", "Accept detected providers and default to project scope").option("--force", "Replace an unmarked colliding BusinessLens skill directory").action(async (options, command) => {
4888
4809
  setExitCode(await runInstall(cwdFor(command), options));
4889
4810
  });
4890
- legacyScopeOptions(program.command("update").summary("Update managed skill installations").description("Update BusinessLens-managed skill installations.").option("--providers <list>", "Limit discovery to: claude,codex,cursor,gemini,github").option("--scope <scope>", "Installation scope: project or global", scope).option("--force", "Replace an unmarked collision inside a managed installation")).action(async (options, command) => {
4811
+ program.command("update").summary("Update managed skill installations").description("Update BusinessLens-managed skill installations.").option("--providers <list>", "Limit discovery to: claude,codex,cursor,gemini,github").option("--scope <scope>", "Installation scope: project or global", scope).option("--force", "Replace an unmarked collision inside a managed installation").action(async (options, command) => {
4891
4812
  setExitCode(await runUpdate(cwdFor(command), options));
4892
4813
  });
4893
4814
  program.command("lint").summary("Lint a Product Model").description("Lint the current .businesslens/ Product Model.").option("--json", "Write the lint result as JSON").action((options, command) => {
@@ -4915,16 +4836,6 @@ function createProgram(setExitCode) {
4915
4836
  blueprint.command("contribute").summary("Contribute a Blueprint").description("Propose the current Product Model for the Blueprint catalog.").option("--yes", "Skip the confirmation prompt").action(async (options, command) => {
4916
4837
  setExitCode(await runContribute(cwdFor(command), { yes: Boolean(options.yes) }));
4917
4838
  });
4918
- for (const name of [
4919
- "export",
4920
- "open",
4921
- "pull",
4922
- "contribute"
4923
- ]) retiredCommand(program, name, `blueprint ${name}`);
4924
- retiredCommand(program, "build", "blueprint export");
4925
- program.command("validate [arguments...]", { hidden: true }).allowUnknownOption(true).action((_arguments, _options, command) => {
4926
- command.error("error: `businesslens validate` has been renamed. Use `businesslens lint`.");
4927
- });
4928
4839
  return program;
4929
4840
  }
4930
4841
  async function main(argv = process.argv) {
@@ -1 +1 @@
1
- <!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="stylesheet" href="/_nuxt/entry.Cn2HYcjJ.css" crossorigin><link rel="modulepreload" as="script" crossorigin href="/_nuxt/BtQ-s_jB.js"><script type="module" src="/_nuxt/BtQ-s_jB.js" crossorigin></script><link rel="prefetch" as="style" crossorigin href="/_nuxt/error-404.VJcZ3YVw.css"><link rel="prefetch" as="script" crossorigin href="/_nuxt/cSnpUPR8.js"><link rel="prefetch" as="style" crossorigin href="/_nuxt/error-500.BwxPsW7a.css"><link rel="prefetch" as="script" crossorigin href="/_nuxt/B-mP848s.js"><script>"use strict";(()=>{const o=window,e=document.documentElement,c=["dark","light"],s=getStorageValue("localStorage","nuxt-color-mode")||"light";let r=s==="system"?f():s;const l=e.getAttribute("data-color-mode-forced");l&&(r=l),i(r),o["__NUXT_COLOR_MODE__"]={preference:s,value:r,getColorScheme:f,addColorScheme:i,removeColorScheme:d};function i(t){const a=""+t+"",n="";e.classList?e.classList.add(a):e.className+=" "+a,n&&e.setAttribute("data-"+n,t)}function d(t){const a=""+t+"",n="";e.classList?e.classList.remove(a):e.className=e.className.replace(new RegExp(a,"g"),""),n&&e.removeAttribute("data-"+n)}function u(t){return o.matchMedia("(prefers-color-scheme"+t+")")}function f(){if(o.matchMedia&&u("").media!=="not all"){for(const t of c)if(u(":"+t).matches)return t}return"light"}})();function getStorageValue(o,e){switch(o){case"localStorage":try{return window.localStorage.getItem(e)}catch{return null}case"sessionStorage":try{return window.sessionStorage.getItem(e)}catch{return null}case"cookie":try{return getCookie(e)}catch{return null}default:return null}}function getCookie(o){const c=("; "+window.document.cookie).split("; "+o+"=");if(c.length===2){const s=c.pop();return s?s.split(";").shift():null}}</script></head><body><div id="__nuxt" class="isolate"></div><div id="teleports"></div><script>window.__NUXT__={};window.__NUXT__.config={public:{pddVersion:"0.12.0"},app:{baseURL:"/",buildId:"5aaede1d-b2e2-4361-9046-383c78ec9ec1",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script><script type="application/json" data-nuxt-data="nuxt-app" data-ssr="false" id="__NUXT_DATA__">[{"prerenderedAt":1,"serverRendered":2},1789070949687,false]</script></body></html>
1
+ <!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="stylesheet" href="/_nuxt/entry.Cn2HYcjJ.css" crossorigin><link rel="modulepreload" as="script" crossorigin href="/_nuxt/BtQ-s_jB.js"><script type="module" src="/_nuxt/BtQ-s_jB.js" crossorigin></script><link rel="prefetch" as="style" crossorigin href="/_nuxt/error-404.VJcZ3YVw.css"><link rel="prefetch" as="script" crossorigin href="/_nuxt/cSnpUPR8.js"><link rel="prefetch" as="style" crossorigin href="/_nuxt/error-500.BwxPsW7a.css"><link rel="prefetch" as="script" crossorigin href="/_nuxt/B-mP848s.js"><script>"use strict";(()=>{const o=window,e=document.documentElement,c=["dark","light"],s=getStorageValue("localStorage","nuxt-color-mode")||"light";let r=s==="system"?f():s;const l=e.getAttribute("data-color-mode-forced");l&&(r=l),i(r),o["__NUXT_COLOR_MODE__"]={preference:s,value:r,getColorScheme:f,addColorScheme:i,removeColorScheme:d};function i(t){const a=""+t+"",n="";e.classList?e.classList.add(a):e.className+=" "+a,n&&e.setAttribute("data-"+n,t)}function d(t){const a=""+t+"",n="";e.classList?e.classList.remove(a):e.className=e.className.replace(new RegExp(a,"g"),""),n&&e.removeAttribute("data-"+n)}function u(t){return o.matchMedia("(prefers-color-scheme"+t+")")}function f(){if(o.matchMedia&&u("").media!=="not all"){for(const t of c)if(u(":"+t).matches)return t}return"light"}})();function getStorageValue(o,e){switch(o){case"localStorage":try{return window.localStorage.getItem(e)}catch{return null}case"sessionStorage":try{return window.sessionStorage.getItem(e)}catch{return null}case"cookie":try{return getCookie(e)}catch{return null}default:return null}}function getCookie(o){const c=("; "+window.document.cookie).split("; "+o+"=");if(c.length===2){const s=c.pop();return s?s.split(";").shift():null}}</script></head><body><div id="__nuxt" class="isolate"></div><div id="teleports"></div><script>window.__NUXT__={};window.__NUXT__.config={public:{pddVersion:"0.13.0"},app:{baseURL:"/",buildId:"371c8694-5c47-4dea-84be-d8bb014327ac",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script><script type="application/json" data-nuxt-data="nuxt-app" data-ssr="false" id="__NUXT_DATA__">[{"prerenderedAt":1,"serverRendered":2},1789218321077,false]</script></body></html>
@@ -1 +1 @@
1
- <!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="stylesheet" href="/_nuxt/entry.Cn2HYcjJ.css" crossorigin><link rel="modulepreload" as="script" crossorigin href="/_nuxt/BtQ-s_jB.js"><script type="module" src="/_nuxt/BtQ-s_jB.js" crossorigin></script><link rel="prefetch" as="style" crossorigin href="/_nuxt/error-404.VJcZ3YVw.css"><link rel="prefetch" as="script" crossorigin href="/_nuxt/cSnpUPR8.js"><link rel="prefetch" as="style" crossorigin href="/_nuxt/error-500.BwxPsW7a.css"><link rel="prefetch" as="script" crossorigin href="/_nuxt/B-mP848s.js"><script>"use strict";(()=>{const o=window,e=document.documentElement,c=["dark","light"],s=getStorageValue("localStorage","nuxt-color-mode")||"light";let r=s==="system"?f():s;const l=e.getAttribute("data-color-mode-forced");l&&(r=l),i(r),o["__NUXT_COLOR_MODE__"]={preference:s,value:r,getColorScheme:f,addColorScheme:i,removeColorScheme:d};function i(t){const a=""+t+"",n="";e.classList?e.classList.add(a):e.className+=" "+a,n&&e.setAttribute("data-"+n,t)}function d(t){const a=""+t+"",n="";e.classList?e.classList.remove(a):e.className=e.className.replace(new RegExp(a,"g"),""),n&&e.removeAttribute("data-"+n)}function u(t){return o.matchMedia("(prefers-color-scheme"+t+")")}function f(){if(o.matchMedia&&u("").media!=="not all"){for(const t of c)if(u(":"+t).matches)return t}return"light"}})();function getStorageValue(o,e){switch(o){case"localStorage":try{return window.localStorage.getItem(e)}catch{return null}case"sessionStorage":try{return window.sessionStorage.getItem(e)}catch{return null}case"cookie":try{return getCookie(e)}catch{return null}default:return null}}function getCookie(o){const c=("; "+window.document.cookie).split("; "+o+"=");if(c.length===2){const s=c.pop();return s?s.split(";").shift():null}}</script></head><body><div id="__nuxt" class="isolate"></div><div id="teleports"></div><script>window.__NUXT__={};window.__NUXT__.config={public:{pddVersion:"0.12.0"},app:{baseURL:"/",buildId:"5aaede1d-b2e2-4361-9046-383c78ec9ec1",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script><script type="application/json" data-nuxt-data="nuxt-app" data-ssr="false" id="__NUXT_DATA__">[{"prerenderedAt":1,"serverRendered":2},1789070949687,false]</script></body></html>
1
+ <!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="stylesheet" href="/_nuxt/entry.Cn2HYcjJ.css" crossorigin><link rel="modulepreload" as="script" crossorigin href="/_nuxt/BtQ-s_jB.js"><script type="module" src="/_nuxt/BtQ-s_jB.js" crossorigin></script><link rel="prefetch" as="style" crossorigin href="/_nuxt/error-404.VJcZ3YVw.css"><link rel="prefetch" as="script" crossorigin href="/_nuxt/cSnpUPR8.js"><link rel="prefetch" as="style" crossorigin href="/_nuxt/error-500.BwxPsW7a.css"><link rel="prefetch" as="script" crossorigin href="/_nuxt/B-mP848s.js"><script>"use strict";(()=>{const o=window,e=document.documentElement,c=["dark","light"],s=getStorageValue("localStorage","nuxt-color-mode")||"light";let r=s==="system"?f():s;const l=e.getAttribute("data-color-mode-forced");l&&(r=l),i(r),o["__NUXT_COLOR_MODE__"]={preference:s,value:r,getColorScheme:f,addColorScheme:i,removeColorScheme:d};function i(t){const a=""+t+"",n="";e.classList?e.classList.add(a):e.className+=" "+a,n&&e.setAttribute("data-"+n,t)}function d(t){const a=""+t+"",n="";e.classList?e.classList.remove(a):e.className=e.className.replace(new RegExp(a,"g"),""),n&&e.removeAttribute("data-"+n)}function u(t){return o.matchMedia("(prefers-color-scheme"+t+")")}function f(){if(o.matchMedia&&u("").media!=="not all"){for(const t of c)if(u(":"+t).matches)return t}return"light"}})();function getStorageValue(o,e){switch(o){case"localStorage":try{return window.localStorage.getItem(e)}catch{return null}case"sessionStorage":try{return window.sessionStorage.getItem(e)}catch{return null}case"cookie":try{return getCookie(e)}catch{return null}default:return null}}function getCookie(o){const c=("; "+window.document.cookie).split("; "+o+"=");if(c.length===2){const s=c.pop();return s?s.split(";").shift():null}}</script></head><body><div id="__nuxt" class="isolate"></div><div id="teleports"></div><script>window.__NUXT__={};window.__NUXT__.config={public:{pddVersion:"0.13.0"},app:{baseURL:"/",buildId:"371c8694-5c47-4dea-84be-d8bb014327ac",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script><script type="application/json" data-nuxt-data="nuxt-app" data-ssr="false" id="__NUXT_DATA__">[{"prerenderedAt":1,"serverRendered":2},1789218321077,false]</script></body></html>
@@ -1 +1 @@
1
- {"id":"5aaede1d-b2e2-4361-9046-383c78ec9ec1","timestamp":1789070903290}
1
+ {"id":"371c8694-5c47-4dea-84be-d8bb014327ac","timestamp":1789218274681}
@@ -0,0 +1 @@
1
+ {"id":"371c8694-5c47-4dea-84be-d8bb014327ac","timestamp":1789218274681,"prerendered":[]}
@@ -1 +1 @@
1
- <!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="stylesheet" href="/_nuxt/entry.Cn2HYcjJ.css" crossorigin><link rel="modulepreload" as="script" crossorigin href="/_nuxt/BtQ-s_jB.js"><script type="module" src="/_nuxt/BtQ-s_jB.js" crossorigin></script><link rel="prefetch" as="style" crossorigin href="/_nuxt/error-404.VJcZ3YVw.css"><link rel="prefetch" as="script" crossorigin href="/_nuxt/cSnpUPR8.js"><link rel="prefetch" as="style" crossorigin href="/_nuxt/error-500.BwxPsW7a.css"><link rel="prefetch" as="script" crossorigin href="/_nuxt/B-mP848s.js"><script>"use strict";(()=>{const o=window,e=document.documentElement,c=["dark","light"],s=getStorageValue("localStorage","nuxt-color-mode")||"light";let r=s==="system"?f():s;const l=e.getAttribute("data-color-mode-forced");l&&(r=l),i(r),o["__NUXT_COLOR_MODE__"]={preference:s,value:r,getColorScheme:f,addColorScheme:i,removeColorScheme:d};function i(t){const a=""+t+"",n="";e.classList?e.classList.add(a):e.className+=" "+a,n&&e.setAttribute("data-"+n,t)}function d(t){const a=""+t+"",n="";e.classList?e.classList.remove(a):e.className=e.className.replace(new RegExp(a,"g"),""),n&&e.removeAttribute("data-"+n)}function u(t){return o.matchMedia("(prefers-color-scheme"+t+")")}function f(){if(o.matchMedia&&u("").media!=="not all"){for(const t of c)if(u(":"+t).matches)return t}return"light"}})();function getStorageValue(o,e){switch(o){case"localStorage":try{return window.localStorage.getItem(e)}catch{return null}case"sessionStorage":try{return window.sessionStorage.getItem(e)}catch{return null}case"cookie":try{return getCookie(e)}catch{return null}default:return null}}function getCookie(o){const c=("; "+window.document.cookie).split("; "+o+"=");if(c.length===2){const s=c.pop();return s?s.split(";").shift():null}}</script></head><body><div id="__nuxt" class="isolate"></div><div id="teleports"></div><script>window.__NUXT__={};window.__NUXT__.config={public:{pddVersion:"0.12.0"},app:{baseURL:"/",buildId:"5aaede1d-b2e2-4361-9046-383c78ec9ec1",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script><script type="application/json" data-nuxt-data="nuxt-app" data-ssr="false" id="__NUXT_DATA__">[{"prerenderedAt":1,"serverRendered":2},1789070949687,false]</script></body></html>
1
+ <!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><link rel="stylesheet" href="/_nuxt/entry.Cn2HYcjJ.css" crossorigin><link rel="modulepreload" as="script" crossorigin href="/_nuxt/BtQ-s_jB.js"><script type="module" src="/_nuxt/BtQ-s_jB.js" crossorigin></script><link rel="prefetch" as="style" crossorigin href="/_nuxt/error-404.VJcZ3YVw.css"><link rel="prefetch" as="script" crossorigin href="/_nuxt/cSnpUPR8.js"><link rel="prefetch" as="style" crossorigin href="/_nuxt/error-500.BwxPsW7a.css"><link rel="prefetch" as="script" crossorigin href="/_nuxt/B-mP848s.js"><script>"use strict";(()=>{const o=window,e=document.documentElement,c=["dark","light"],s=getStorageValue("localStorage","nuxt-color-mode")||"light";let r=s==="system"?f():s;const l=e.getAttribute("data-color-mode-forced");l&&(r=l),i(r),o["__NUXT_COLOR_MODE__"]={preference:s,value:r,getColorScheme:f,addColorScheme:i,removeColorScheme:d};function i(t){const a=""+t+"",n="";e.classList?e.classList.add(a):e.className+=" "+a,n&&e.setAttribute("data-"+n,t)}function d(t){const a=""+t+"",n="";e.classList?e.classList.remove(a):e.className=e.className.replace(new RegExp(a,"g"),""),n&&e.removeAttribute("data-"+n)}function u(t){return o.matchMedia("(prefers-color-scheme"+t+")")}function f(){if(o.matchMedia&&u("").media!=="not all"){for(const t of c)if(u(":"+t).matches)return t}return"light"}})();function getStorageValue(o,e){switch(o){case"localStorage":try{return window.localStorage.getItem(e)}catch{return null}case"sessionStorage":try{return window.sessionStorage.getItem(e)}catch{return null}case"cookie":try{return getCookie(e)}catch{return null}default:return null}}function getCookie(o){const c=("; "+window.document.cookie).split("; "+o+"=");if(c.length===2){const s=c.pop();return s?s.split(";").shift():null}}</script></head><body><div id="__nuxt" class="isolate"></div><div id="teleports"></div><script>window.__NUXT__={};window.__NUXT__.config={public:{pddVersion:"0.13.0"},app:{baseURL:"/",buildId:"371c8694-5c47-4dea-84be-d8bb014327ac",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script><script type="application/json" data-nuxt-data="nuxt-app" data-ssr="false" id="__NUXT_DATA__">[{"prerenderedAt":1,"serverRendered":2},1789218321078,false]</script></body></html>
@@ -59,7 +59,8 @@ install by another tool, or an installation predating the marker — and it stop
59
59
  the run unless `--force` is explicit. BusinessLens does not read a directory's
60
60
  contents to guess that it wrote it: guessing wrong costs someone work they
61
61
  cannot recover. For the same reason, a skill this release no longer ships is
62
- removed only where the marker recorded it.
62
+ removed only where the marker recorded a `businesslens-*` name. Bare-name skills
63
+ and command files are outside the current installer contract.
63
64
 
64
65
  **A refusal changes nothing.** Every selected harness is checked before any is
65
66
  written, so an install for two harnesses that stops on the second leaves the
package/docs/cli.md CHANGED
@@ -26,6 +26,8 @@ npx businesslens <command> [options]
26
26
  | [`blueprint contribute`](./cli-contribute.md) | Propose a Blueprint by pull request |
27
27
 
28
28
  Global options are `-c, --cwd <path>`, `-h, --help`, and `-V, --version`.
29
+ Only documented commands and options are accepted; removed spellings produce
30
+ normal usage errors. Installation scope uses `--scope project|global`.
29
31
  Each command's help lists only the arguments and options that command accepts:
30
32
 
31
33
  ```bash
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "businesslens",
3
- "version": "0.12.0",
3
+ "version": "0.13.0",
4
4
  "description": "Product-Driven Development for coding agents: a git-tracked Product Model in .businesslens/, verified against implementation.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -1 +0,0 @@
1
- {"id":"5aaede1d-b2e2-4361-9046-383c78ec9ec1","timestamp":1789070903290,"prerendered":[]}