@thebassclef/lite 1.9.6 → 1.9.8

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/README.md CHANGED
@@ -63,7 +63,7 @@ your browser.
63
63
 
64
64
  ## Current release
65
65
 
66
- <!-- version-start -->1.9.6<!-- version-end -->
66
+ <!-- version-start -->1.9.8<!-- version-end -->
67
67
 
68
68
  See [CHANGELOG.md](CHANGELOG.md) for the full changelog. Adopter-facing
69
69
  release notes live at [docs.bassclef.dev/docs/whats-new/releases](https://docs.bassclef.dev/docs/whats-new/releases).
package/dist/cli.cjs CHANGED
@@ -810,15 +810,19 @@ function dirExists(p) {
810
810
  }
811
811
  const STATUSLINE_FIELD = {
812
812
  type: "command",
813
- command: "bash ~/.claude/bassclef-statusline.sh"
813
+ command: "bash ~/.claude/bassclef-statusline-dispatcher.sh"
814
814
  };
815
+ const LEGACY_STATUSLINE_COMMAND = "bash ~/.claude/bassclef-statusline.sh";
815
816
  const DISPATCHER_REL = ["dist", "lite", "presence", "cli", "bassclef-statusline.dispatcher.sh"];
816
- const USER_DISPATCHER_REL = [".claude", "bassclef-statusline.sh"];
817
+ const RICH_IMPL_REL = ["dist", "lite", "presence", "cli", "bassclef-statusline.sh"];
818
+ const USER_DISPATCHER_REL = [".claude", "bassclef-statusline-dispatcher.sh"];
819
+ const USER_RICH_IMPL_REL = [".claude", "bassclef-statusline.sh"];
817
820
  const PROJECT_SETTINGS_REL = [".claude", "settings.json"];
818
821
  function installStatusline(opts) {
819
822
  if (opts.skip) {
820
823
  return {
821
824
  dispatcher: skipped(node_path.join(opts.home, ...USER_DISPATCHER_REL)),
825
+ rich: skipped(node_path.join(opts.home, ...USER_RICH_IMPL_REL)),
822
826
  settings: skipped(node_path.join(opts.projectDir, ...PROJECT_SETTINGS_REL))
823
827
  };
824
828
  }
@@ -828,10 +832,18 @@ function installStatusline(opts) {
828
832
  `bassclef init: cannot install statusline — bundled dispatcher missing at ${dispatcherSource}. Reinstall @thebassclef/lite or file a bug.`
829
833
  );
830
834
  }
831
- const sourceBody = node_fs.readFileSync(dispatcherSource, "utf8");
832
- const dispatcher = handleDispatcher(opts, dispatcherSource, sourceBody);
835
+ const richImplSource = node_path.join(opts.packageDir, ...RICH_IMPL_REL);
836
+ if (!node_fs.existsSync(richImplSource)) {
837
+ throw new Error(
838
+ `bassclef init: cannot install statusline — bundled bassclef-statusline.sh missing at ${richImplSource}. Reinstall @thebassclef/lite or file a bug.`
839
+ );
840
+ }
841
+ const dispatcherBody = node_fs.readFileSync(dispatcherSource, "utf8");
842
+ const richBody = node_fs.readFileSync(richImplSource, "utf8");
843
+ const dispatcher = handleDispatcher(opts, dispatcherSource, dispatcherBody);
844
+ const rich = handleRichImpl(opts, richImplSource, richBody);
833
845
  const settings = handleSettings(opts);
834
- return { dispatcher, settings };
846
+ return { dispatcher, rich, settings };
835
847
  }
836
848
  function handleDispatcher(opts, sourcePath, sourceBody) {
837
849
  const target = node_path.join(opts.home, ...USER_DISPATCHER_REL);
@@ -873,6 +885,57 @@ function handleDispatcher(opts, sourcePath, sourceBody) {
873
885
  writeExec(target, sourceBody);
874
886
  return { kind: "replaced", path: target, detail: `Overwrote ${target} (--force) with bundled dispatcher.` };
875
887
  }
888
+ function handleRichImpl(opts, sourcePath, sourceBody) {
889
+ const target = node_path.join(opts.home, ...USER_RICH_IMPL_REL);
890
+ if (opts.dryRun) {
891
+ return {
892
+ kind: "would-install",
893
+ path: target,
894
+ detail: `Dry-run: would copy ${sourcePath} → ${target} (0755).`
895
+ };
896
+ }
897
+ if (!node_fs.existsSync(target)) {
898
+ writeExec(target, sourceBody);
899
+ return { kind: "installed", path: target, detail: `Wrote ${target} (0755) from bundled rich impl.` };
900
+ }
901
+ const st = node_fs.lstatSync(target);
902
+ if (st.isSymbolicLink()) {
903
+ if (!opts.force) {
904
+ return {
905
+ kind: "preserved",
906
+ path: target,
907
+ detail: `${target} is a symlink; refusing to follow. Pass --force to replace.`
908
+ };
909
+ }
910
+ node_fs.unlinkSync(target);
911
+ writeExec(target, sourceBody);
912
+ return { kind: "replaced", path: target, detail: `Replaced symlink at ${target} with bundled rich impl.` };
913
+ }
914
+ const existing = node_fs.readFileSync(target, "utf8");
915
+ if (existing === sourceBody) {
916
+ return { kind: "unchanged", path: target, detail: `${target} already matches bundled rich impl.` };
917
+ }
918
+ if (isLegacyDispatcher(existing)) {
919
+ writeExec(target, sourceBody);
920
+ return {
921
+ kind: "replaced",
922
+ path: target,
923
+ detail: `Migrated ${target} from legacy dispatcher to rich impl (cli#281 upgrade path).`
924
+ };
925
+ }
926
+ if (!opts.force) {
927
+ return {
928
+ kind: "preserved",
929
+ path: target,
930
+ detail: `${target} differs from bundled rich impl. Pass --force to overwrite.`
931
+ };
932
+ }
933
+ writeExec(target, sourceBody);
934
+ return { kind: "replaced", path: target, detail: `Overwrote ${target} (--force) with bundled rich impl.` };
935
+ }
936
+ function isLegacyDispatcher(body) {
937
+ return body.includes("BASSCLEF_SYNC_VERSION=thin-pointer-statusline-");
938
+ }
876
939
  function handleSettings(opts) {
877
940
  const target = node_path.join(opts.projectDir, ...PROJECT_SETTINGS_REL);
878
941
  if (opts.settingsPreserved) {
@@ -900,6 +963,15 @@ function handleSettings(opts) {
900
963
  if (matchesDesired(current)) {
901
964
  return { kind: "unchanged", path: target, detail: `${target} already carries the bassclef statusLine.` };
902
965
  }
966
+ if (isLegacyStatuslineCommand(current)) {
967
+ const next2 = { ...existing, statusLine: desired };
968
+ writeSettings(target, next2);
969
+ return {
970
+ kind: "replaced",
971
+ path: target,
972
+ detail: `Migrated statusLine in ${target} from legacy dispatcher path to new dispatcher path (cli#281 upgrade).`
973
+ };
974
+ }
903
975
  if (!opts.force) {
904
976
  return {
905
977
  kind: "preserved",
@@ -911,6 +983,11 @@ function handleSettings(opts) {
911
983
  writeSettings(target, next);
912
984
  return { kind: "replaced", path: target, detail: `Overwrote statusLine in ${target} (--force).` };
913
985
  }
986
+ function isLegacyStatuslineCommand(current) {
987
+ if (!current || typeof current !== "object" || Array.isArray(current)) return false;
988
+ const c = current;
989
+ return c.type === "command" && c.command === LEGACY_STATUSLINE_COMMAND;
990
+ }
914
991
  function skipped(path) {
915
992
  return {
916
993
  kind: "skipped",
@@ -1647,15 +1724,16 @@ function maybeEmitStatuslinePlan(opts) {
1647
1724
  return;
1648
1725
  }
1649
1726
  const dv = report.dispatcher.kind;
1727
+ const rv = report.rich.kind;
1650
1728
  const sv = report.settings.kind;
1651
- if (dv === "skipped" && sv === "skipped") {
1729
+ if (dv === "skipped" && rv === "skipped" && sv === "skipped") {
1652
1730
  opts.say(`bassclef init: statusline install skipped (--skip-statusline).
1653
1731
  `);
1654
1732
  return;
1655
1733
  }
1656
1734
  if (opts.dryRun) {
1657
1735
  opts.say(
1658
- `bassclef init: would install statusline dispatcher at ${report.dispatcher.path} and set statusLine in ${report.settings.path}.
1736
+ `bassclef init: would install statusline dispatcher at ${report.dispatcher.path}, rich impl at ${report.rich.path}, and set statusLine in ${report.settings.path}.
1659
1737
  `
1660
1738
  );
1661
1739
  return;
@@ -1665,6 +1743,10 @@ function maybeEmitStatuslinePlan(opts) {
1665
1743
  else if (dv === "replaced") parts.push(`replaced ${report.dispatcher.path} (--force)`);
1666
1744
  else if (dv === "preserved") parts.push(`preserved ${report.dispatcher.path} (pass --force to overwrite)`);
1667
1745
  else if (dv === "unchanged") parts.push(`${report.dispatcher.path} already matches bundle`);
1746
+ if (rv === "installed") parts.push(`wrote ${report.rich.path}`);
1747
+ else if (rv === "replaced") parts.push(`replaced ${report.rich.path} (migration or --force)`);
1748
+ else if (rv === "preserved") parts.push(`preserved ${report.rich.path} (pass --force to overwrite)`);
1749
+ else if (rv === "unchanged") parts.push(`${report.rich.path} already matches bundle`);
1668
1750
  if (sv === "installed") parts.push(`set statusLine in ${report.settings.path}`);
1669
1751
  else if (sv === "replaced") parts.push(`replaced statusLine in ${report.settings.path} (--force)`);
1670
1752
  else if (sv === "preserved") parts.push(`preserved statusLine in ${report.settings.path} (pass --force to overwrite)`);
package/dist/cli.js CHANGED
@@ -787,15 +787,19 @@ function dirExists(p) {
787
787
  }
788
788
  const STATUSLINE_FIELD = {
789
789
  type: "command",
790
- command: "bash ~/.claude/bassclef-statusline.sh"
790
+ command: "bash ~/.claude/bassclef-statusline-dispatcher.sh"
791
791
  };
792
+ const LEGACY_STATUSLINE_COMMAND = "bash ~/.claude/bassclef-statusline.sh";
792
793
  const DISPATCHER_REL = ["dist", "lite", "presence", "cli", "bassclef-statusline.dispatcher.sh"];
793
- const USER_DISPATCHER_REL = [".claude", "bassclef-statusline.sh"];
794
+ const RICH_IMPL_REL = ["dist", "lite", "presence", "cli", "bassclef-statusline.sh"];
795
+ const USER_DISPATCHER_REL = [".claude", "bassclef-statusline-dispatcher.sh"];
796
+ const USER_RICH_IMPL_REL = [".claude", "bassclef-statusline.sh"];
794
797
  const PROJECT_SETTINGS_REL = [".claude", "settings.json"];
795
798
  function installStatusline(opts) {
796
799
  if (opts.skip) {
797
800
  return {
798
801
  dispatcher: skipped(join(opts.home, ...USER_DISPATCHER_REL)),
802
+ rich: skipped(join(opts.home, ...USER_RICH_IMPL_REL)),
799
803
  settings: skipped(join(opts.projectDir, ...PROJECT_SETTINGS_REL))
800
804
  };
801
805
  }
@@ -805,10 +809,18 @@ function installStatusline(opts) {
805
809
  `bassclef init: cannot install statusline — bundled dispatcher missing at ${dispatcherSource}. Reinstall @thebassclef/lite or file a bug.`
806
810
  );
807
811
  }
808
- const sourceBody = readFileSync(dispatcherSource, "utf8");
809
- const dispatcher = handleDispatcher(opts, dispatcherSource, sourceBody);
812
+ const richImplSource = join(opts.packageDir, ...RICH_IMPL_REL);
813
+ if (!existsSync(richImplSource)) {
814
+ throw new Error(
815
+ `bassclef init: cannot install statusline — bundled bassclef-statusline.sh missing at ${richImplSource}. Reinstall @thebassclef/lite or file a bug.`
816
+ );
817
+ }
818
+ const dispatcherBody = readFileSync(dispatcherSource, "utf8");
819
+ const richBody = readFileSync(richImplSource, "utf8");
820
+ const dispatcher = handleDispatcher(opts, dispatcherSource, dispatcherBody);
821
+ const rich = handleRichImpl(opts, richImplSource, richBody);
810
822
  const settings = handleSettings(opts);
811
- return { dispatcher, settings };
823
+ return { dispatcher, rich, settings };
812
824
  }
813
825
  function handleDispatcher(opts, sourcePath, sourceBody) {
814
826
  const target = join(opts.home, ...USER_DISPATCHER_REL);
@@ -850,6 +862,57 @@ function handleDispatcher(opts, sourcePath, sourceBody) {
850
862
  writeExec(target, sourceBody);
851
863
  return { kind: "replaced", path: target, detail: `Overwrote ${target} (--force) with bundled dispatcher.` };
852
864
  }
865
+ function handleRichImpl(opts, sourcePath, sourceBody) {
866
+ const target = join(opts.home, ...USER_RICH_IMPL_REL);
867
+ if (opts.dryRun) {
868
+ return {
869
+ kind: "would-install",
870
+ path: target,
871
+ detail: `Dry-run: would copy ${sourcePath} → ${target} (0755).`
872
+ };
873
+ }
874
+ if (!existsSync(target)) {
875
+ writeExec(target, sourceBody);
876
+ return { kind: "installed", path: target, detail: `Wrote ${target} (0755) from bundled rich impl.` };
877
+ }
878
+ const st = lstatSync(target);
879
+ if (st.isSymbolicLink()) {
880
+ if (!opts.force) {
881
+ return {
882
+ kind: "preserved",
883
+ path: target,
884
+ detail: `${target} is a symlink; refusing to follow. Pass --force to replace.`
885
+ };
886
+ }
887
+ unlinkSync(target);
888
+ writeExec(target, sourceBody);
889
+ return { kind: "replaced", path: target, detail: `Replaced symlink at ${target} with bundled rich impl.` };
890
+ }
891
+ const existing = readFileSync(target, "utf8");
892
+ if (existing === sourceBody) {
893
+ return { kind: "unchanged", path: target, detail: `${target} already matches bundled rich impl.` };
894
+ }
895
+ if (isLegacyDispatcher(existing)) {
896
+ writeExec(target, sourceBody);
897
+ return {
898
+ kind: "replaced",
899
+ path: target,
900
+ detail: `Migrated ${target} from legacy dispatcher to rich impl (cli#281 upgrade path).`
901
+ };
902
+ }
903
+ if (!opts.force) {
904
+ return {
905
+ kind: "preserved",
906
+ path: target,
907
+ detail: `${target} differs from bundled rich impl. Pass --force to overwrite.`
908
+ };
909
+ }
910
+ writeExec(target, sourceBody);
911
+ return { kind: "replaced", path: target, detail: `Overwrote ${target} (--force) with bundled rich impl.` };
912
+ }
913
+ function isLegacyDispatcher(body) {
914
+ return body.includes("BASSCLEF_SYNC_VERSION=thin-pointer-statusline-");
915
+ }
853
916
  function handleSettings(opts) {
854
917
  const target = join(opts.projectDir, ...PROJECT_SETTINGS_REL);
855
918
  if (opts.settingsPreserved) {
@@ -877,6 +940,15 @@ function handleSettings(opts) {
877
940
  if (matchesDesired(current)) {
878
941
  return { kind: "unchanged", path: target, detail: `${target} already carries the bassclef statusLine.` };
879
942
  }
943
+ if (isLegacyStatuslineCommand(current)) {
944
+ const next2 = { ...existing, statusLine: desired };
945
+ writeSettings(target, next2);
946
+ return {
947
+ kind: "replaced",
948
+ path: target,
949
+ detail: `Migrated statusLine in ${target} from legacy dispatcher path to new dispatcher path (cli#281 upgrade).`
950
+ };
951
+ }
880
952
  if (!opts.force) {
881
953
  return {
882
954
  kind: "preserved",
@@ -888,6 +960,11 @@ function handleSettings(opts) {
888
960
  writeSettings(target, next);
889
961
  return { kind: "replaced", path: target, detail: `Overwrote statusLine in ${target} (--force).` };
890
962
  }
963
+ function isLegacyStatuslineCommand(current) {
964
+ if (!current || typeof current !== "object" || Array.isArray(current)) return false;
965
+ const c = current;
966
+ return c.type === "command" && c.command === LEGACY_STATUSLINE_COMMAND;
967
+ }
891
968
  function skipped(path) {
892
969
  return {
893
970
  kind: "skipped",
@@ -1624,15 +1701,16 @@ function maybeEmitStatuslinePlan(opts) {
1624
1701
  return;
1625
1702
  }
1626
1703
  const dv = report.dispatcher.kind;
1704
+ const rv = report.rich.kind;
1627
1705
  const sv = report.settings.kind;
1628
- if (dv === "skipped" && sv === "skipped") {
1706
+ if (dv === "skipped" && rv === "skipped" && sv === "skipped") {
1629
1707
  opts.say(`bassclef init: statusline install skipped (--skip-statusline).
1630
1708
  `);
1631
1709
  return;
1632
1710
  }
1633
1711
  if (opts.dryRun) {
1634
1712
  opts.say(
1635
- `bassclef init: would install statusline dispatcher at ${report.dispatcher.path} and set statusLine in ${report.settings.path}.
1713
+ `bassclef init: would install statusline dispatcher at ${report.dispatcher.path}, rich impl at ${report.rich.path}, and set statusLine in ${report.settings.path}.
1636
1714
  `
1637
1715
  );
1638
1716
  return;
@@ -1642,6 +1720,10 @@ function maybeEmitStatuslinePlan(opts) {
1642
1720
  else if (dv === "replaced") parts.push(`replaced ${report.dispatcher.path} (--force)`);
1643
1721
  else if (dv === "preserved") parts.push(`preserved ${report.dispatcher.path} (pass --force to overwrite)`);
1644
1722
  else if (dv === "unchanged") parts.push(`${report.dispatcher.path} already matches bundle`);
1723
+ if (rv === "installed") parts.push(`wrote ${report.rich.path}`);
1724
+ else if (rv === "replaced") parts.push(`replaced ${report.rich.path} (migration or --force)`);
1725
+ else if (rv === "preserved") parts.push(`preserved ${report.rich.path} (pass --force to overwrite)`);
1726
+ else if (rv === "unchanged") parts.push(`${report.rich.path} already matches bundle`);
1645
1727
  if (sv === "installed") parts.push(`set statusLine in ${report.settings.path}`);
1646
1728
  else if (sv === "replaced") parts.push(`replaced statusLine in ${report.settings.path} (--force)`);
1647
1729
  else if (sv === "preserved") parts.push(`preserved statusLine in ${report.settings.path} (pass --force to overwrite)`);
package/dist/index.cjs CHANGED
@@ -1,4 +1,4 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const version = "1.9.6";
3
+ const version = "1.9.8";
4
4
  exports.version = version;
package/dist/index.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export declare const version: "1.9.6";
1
+ export declare const version: "1.9.8";
2
2
  //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- const version = "1.9.6";
1
+ const version = "1.9.8";
2
2
  export {
3
3
  version
4
4
  };
@@ -236,6 +236,6 @@
236
236
  "$schema": "https://bassclef.sunj-labs/state-spine/v0/schemas/bassclef-wiring-manifest.schema.json",
237
237
  "statusLine": {
238
238
  "type": "command",
239
- "command": "bash ~/.claude/bassclef-statusline.sh"
239
+ "command": "bash ~/.claude/bassclef-statusline-dispatcher.sh"
240
240
  }
241
241
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thebassclef/lite",
3
- "version": "1.9.6",
3
+ "version": "1.9.8",
4
4
  "description": "Bassclef CLI — install and upgrade bassclef in your project with two commands.",
5
5
  "keywords": [
6
6
  "bassclef",