@basou/cli 0.47.0 → 0.48.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/dist/index.js CHANGED
@@ -1260,14 +1260,16 @@ Input format (a JSON array; one object per decision):
1260
1260
  }
1261
1261
  ]
1262
1262
 
1263
- "title" is required. "kind" names the vessel: "track" records a strategic,
1264
- UNFINISHED direction (+ why) and orientation/handoff resurface it every session
1265
- until you close it with 'basou decision void <id>', while "decision" records a
1266
- point-in-time call (surfaced only as the latest). Every other field is optional.
1263
+ "title" and "kind" are both required. "kind" names the vessel: "track" records a
1264
+ strategic, UNFINISHED direction (+ why) and orientation/handoff resurface it
1265
+ every session until you close it with 'basou decision void <id>', while
1266
+ "decision" records a point-in-time call (surfaced as the latest). Every other
1267
+ field is optional.
1267
1268
 
1268
- DEPRECATED: omitting "kind" still writes the item, as a decision, but warns --
1269
- and becomes an ERROR in the next release. It has no default because getting it
1270
- wrong fails silently: a track filed as a decision simply never comes back.
1269
+ "kind" has no default because getting it wrong fails silently: a track filed as
1270
+ a decision never enters the open-track list, so nothing holds it there -- the
1271
+ next decision simply takes its place. Omitting it on ANY item refuses the whole
1272
+ batch and writes nothing, so a partial write can never be reported as a success.
1271
1273
  All decisions are written into one ad-hoc session timestamped now, so
1272
1274
  orientation surfaces them as the latest decisions. Run from a workspace-view
1273
1275
  directory and it resolves to the planning repo, like 'basou orient' /
@@ -1311,14 +1313,6 @@ async function warnLinkedFilesOutsideRoots(input) {
1311
1313
  } catch {
1312
1314
  }
1313
1315
  }
1314
- function warnMissingKind(decisions, indices) {
1315
- for (const index of indices) {
1316
- const title = (decisions[index]?.title ?? "").trim();
1317
- console.error(
1318
- `basou: decision[${index}] ("${title.slice(0, 40)}") declares no "kind" \u2014 it is recorded as a point-in-time decision and will NOT resurface in orient. Set "kind": "track" for an unfinished direction, or "kind": "decision" to say it is settled. Omitting it becomes an ERROR in the next release.`
1319
- );
1320
- }
1321
- }
1322
1316
  async function doRunDecisionRecord(options, ctx) {
1323
1317
  const cwd = ctx.cwd ?? process.cwd();
1324
1318
  const repositoryRoot = await resolveRepositoryRootForDecision(cwd);
@@ -1416,8 +1410,7 @@ async function doRunDecisionCapture(options, ctx) {
1416
1410
  const paths = basouPaths4(repositoryRoot);
1417
1411
  await assertWorkspaceInitialized2(paths.root);
1418
1412
  const raw = await readCaptureInput(options, ctx);
1419
- const { decisions, missingKind } = parseCaptureInput(raw);
1420
- warnMissingKind(decisions, missingKind);
1413
+ const { decisions } = parseCaptureInput(raw);
1421
1414
  await warnLinkedFilesOutsideRoots({
1422
1415
  linkedFiles: decisions.flatMap((d) => d.linked_files ?? []),
1423
1416
  cwd,
@@ -1680,12 +1673,30 @@ function parseCaptureInput(raw) {
1680
1673
  }
1681
1674
  const decisions = [];
1682
1675
  const missingKind = [];
1683
- parsed.forEach((item, index) => {
1684
- const input = validateCaptureItem(item, index);
1685
- decisions.push(input);
1686
- if (input.kind === void 0) missingKind.push(index);
1687
- });
1688
- return { decisions, missingKind };
1676
+ try {
1677
+ parsed.forEach((item, index) => {
1678
+ const input = validateCaptureItem(item, index);
1679
+ decisions.push(input);
1680
+ if (input.kind === void 0) missingKind.push(index);
1681
+ });
1682
+ } catch (error) {
1683
+ const detail = error instanceof Error ? error.message : String(error);
1684
+ throw new Error(`${detail} ${batchDisposition(parsed.length)}`, { cause: error });
1685
+ }
1686
+ if (missingKind.length > 0) {
1687
+ throw new Error(`${missingKindError(missingKind)} ${batchDisposition(parsed.length)}`);
1688
+ }
1689
+ return { decisions };
1690
+ }
1691
+ var MISSING_KIND_SAMPLE = 10;
1692
+ function batchDisposition(total) {
1693
+ return `Nothing was written: all ${total} item(s) in this batch were refused.`;
1694
+ }
1695
+ function missingKindError(indices) {
1696
+ const shown = indices.slice(0, MISSING_KIND_SAMPLE).map((i) => `decision[${i}]`);
1697
+ const overflow = indices.length - shown.length;
1698
+ const list = overflow > 0 ? `${shown.join(", ")} (... +${overflow} more)` : shown.join(", ");
1699
+ return `${list}: "kind" is required. It names the vessel: "track" for an unfinished direction, which orient keeps in its open-track list until you close it with 'basou decision void', or "decision" for a settled point-in-time call, which the next decision replaces. Add "kind" to every item and re-run.`;
1689
1700
  }
1690
1701
  function validateCaptureItem(item, index) {
1691
1702
  if (typeof item !== "object" || item === null || Array.isArray(item)) {
@@ -1702,11 +1713,11 @@ function validateCaptureItem(item, index) {
1702
1713
  if (typeof obj.title !== "string" || isBlank(obj.title)) {
1703
1714
  throw new Error(`decision[${index}].title must be a non-empty string.`);
1704
1715
  }
1716
+ if (obj.kind !== void 0 && obj.kind !== "decision" && obj.kind !== "track") {
1717
+ throw new Error(`decision[${index}].kind must be "decision" or "track", got '${obj.kind}'.`);
1718
+ }
1705
1719
  const out = { title: obj.title };
1706
1720
  if (obj.kind !== void 0) {
1707
- if (obj.kind !== "decision" && obj.kind !== "track") {
1708
- throw new Error(`decision[${index}].kind must be "decision" or "track", got '${obj.kind}'.`);
1709
- }
1710
1721
  out.kind = obj.kind;
1711
1722
  }
1712
1723
  if (obj.rationale !== void 0) {
@@ -1798,12 +1809,10 @@ function captureItemToPayload(item) {
1798
1809
  return payload;
1799
1810
  }
1800
1811
  function previewKindMarker(kind) {
1801
- if (kind === "track") return " [TRACK]";
1802
- return kind === "decision" ? " [DECISION]" : " [NO KIND]";
1812
+ return kind === "track" ? " [TRACK]" : " [DECISION]";
1803
1813
  }
1804
1814
  function recordedKindMarker(kind) {
1805
- if (kind === "track") return " [TRACK]";
1806
- return kind === "decision" ? "" : " [NO KIND]";
1815
+ return kind === "track" ? " [TRACK]" : "";
1807
1816
  }
1808
1817
  function printCapturePreview(options, decisions) {
1809
1818
  if (options.json === true) {
@@ -1942,13 +1951,14 @@ function printDecisionResult(options, result) {
1942
1951
  }
1943
1952
  const trackPrefix = result.rich.kind === "track" ? "track " : "";
1944
1953
  const rationaleSuffix = result.rich.rationale !== void 0 ? ` (rationale: ${result.rich.rationale})` : "";
1954
+ const vesselSuffix = result.rich.kind === "track" ? "" : " \u2014 a point-in-time decision, not an open track (use --track for a direction that should keep coming back until you close it)";
1945
1955
  if (result.mode === "ad-hoc") {
1946
1956
  console.log(
1947
- `Recorded ${trackPrefix}${result.decisionId} in ad-hoc session ${sid}${rationaleSuffix}`
1957
+ `Recorded ${trackPrefix}${result.decisionId} in ad-hoc session ${sid}${rationaleSuffix}${vesselSuffix}`
1948
1958
  );
1949
1959
  } else {
1950
1960
  console.log(
1951
- `Recorded ${trackPrefix}${result.decisionId} in session ${sid} (${result.sessionStatus})${rationaleSuffix}`
1961
+ `Recorded ${trackPrefix}${result.decisionId} in session ${sid} (${result.sessionStatus})${rationaleSuffix}${vesselSuffix}`
1952
1962
  );
1953
1963
  }
1954
1964
  }
@@ -13805,7 +13815,7 @@ async function assertWorkspaceInitialized15(basouRoot) {
13805
13815
  function readBuildStamp() {
13806
13816
  if (false) return void 0;
13807
13817
  try {
13808
- return JSON.parse('{"version":"0.47.0","commit":"831e0cb","committedAt":"2026-09-20T22:28:13+09:00"}');
13818
+ return JSON.parse('{"version":"0.48.0","commit":"2e8fee7","committedAt":"2026-09-21T11:35:12+09:00"}');
13809
13819
  } catch {
13810
13820
  return void 0;
13811
13821
  }