truecourse 0.6.0-next.0 → 0.6.0-next.2

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/cli.mjs CHANGED
@@ -128242,7 +128242,7 @@ function readToolVersion() {
128242
128242
  if (cachedVersion)
128243
128243
  return cachedVersion;
128244
128244
  if (true) {
128245
- cachedVersion = "0.6.0-next.0";
128245
+ cachedVersion = "0.6.0-next.2";
128246
128246
  return cachedVersion;
128247
128247
  }
128248
128248
  try {
@@ -146142,6 +146142,10 @@ async function filterByRelevance(repoRoot5, docs, opts = {}) {
146142
146142
  const manualSet = new Set(opts.manualIncludes ?? []);
146143
146143
  const runner = opts.runner ?? spawnRelevanceRunner({ model: opts.model, fallbackModel: opts.fallbackModel });
146144
146144
  const concurrency = opts.concurrency ?? 4;
146145
+ const total = docs.length;
146146
+ let done = 0;
146147
+ const markDone = () => opts.onProgress?.(++done, total);
146148
+ opts.onProgress?.(0, total);
146145
146149
  const verdicts = /* @__PURE__ */ new Map();
146146
146150
  let cursor = 0;
146147
146151
  let active = 0;
@@ -146151,6 +146155,7 @@ async function filterByRelevance(repoRoot5, docs, opts = {}) {
146151
146155
  const doc = docs[cursor++];
146152
146156
  if (manualSet.has(doc.path)) {
146153
146157
  verdicts.set(doc.path, { path: doc.path, include: true, reason: "manual include" });
146158
+ markDone();
146154
146159
  if (cursor >= docs.length && active === 0)
146155
146160
  resolve9();
146156
146161
  continue;
@@ -146165,6 +146170,7 @@ async function filterByRelevance(repoRoot5, docs, opts = {}) {
146165
146170
  reason: "classification failed; defaulting to include"
146166
146171
  });
146167
146172
  }).finally(() => {
146173
+ markDone();
146168
146174
  active--;
146169
146175
  if (cursor >= docs.length && active === 0)
146170
146176
  resolve9();
@@ -146551,7 +146557,8 @@ async function consolidate(repoRoot5, opts = {}) {
146551
146557
  enabled: opts.disableRelevanceFilter !== true,
146552
146558
  manualIncludes: decisions.manualIncludes ?? [],
146553
146559
  model: models.relevance,
146554
- fallbackModel
146560
+ fallbackModel,
146561
+ onProgress: opts.onRelevanceProgress
146555
146562
  });
146556
146563
  const docs = relevance.included;
146557
146564
  const skippedDocs = relevance.skipped.map(({ doc, reason }) => ({ path: doc.path, reason }));
@@ -148586,6 +148593,10 @@ async function scanInProcess(repoRoot5, options = {}) {
148586
148593
  disableLlmChainDetection: options.disableLlmChainDetection,
148587
148594
  skipGit: options.skipGit,
148588
148595
  models: resolveConsolidateModels(repoRoot5),
148596
+ onRelevanceProgress: (doneCount, total) => {
148597
+ if (total > 0)
148598
+ tracker?.detail("discover", `${doneCount}/${total} docs`);
148599
+ },
148589
148600
  onDocStart: () => {
148590
148601
  if (!extractStarted) {
148591
148602
  tracker?.done("discover");
@@ -149330,12 +149341,18 @@ async function runSpecScan(opts = {}) {
149330
149341
  O2.message("Open conflicts:");
149331
149342
  for (const c2 of merge2.openConflicts.slice(0, 10)) {
149332
149343
  O2.message(` \u2022 ${c2.subject} (${c2.candidates.length} candidates, default: ${c2.candidates[c2.defaultPick].claim.provenance.file})`);
149344
+ O2.message(` id: ${c2.id}`);
149333
149345
  }
149334
149346
  if (merge2.openConflicts.length > 10) {
149335
- O2.message(` \u2026 (+${merge2.openConflicts.length - 10} more)`);
149347
+ O2.message(` \u2026 (+${merge2.openConflicts.length - 10} more \u2014 run \`truecourse spec conflicts list\`)`);
149336
149348
  }
149337
149349
  O2.message("");
149338
- O2.message("Resolve in the dashboard, or run `truecourse spec resolve --all-defaults`.");
149350
+ O2.message("Resolve them:");
149351
+ O2.message(" \u2022 dashboard: truecourse dashboard (Spec tab)");
149352
+ O2.message(" \u2022 per conflict: truecourse spec conflicts show <id>");
149353
+ O2.message(" truecourse spec conflicts pick <id> <candidateIndex>");
149354
+ O2.message(' truecourse spec conflicts custom <id> --text "\u2026"');
149355
+ O2.message(" \u2022 accept defaults: truecourse spec resolve --all-defaults");
149339
149356
  }
149340
149357
  gt(merge2.openConflicts.length === 0 ? "No open conflicts." : `${merge2.openConflicts.length} open.`);
149341
149358
  } catch (e) {
@@ -149514,7 +149531,7 @@ function decisionsRelPath(root) {
149514
149531
  init_dist4();
149515
149532
  init_progress();
149516
149533
  var repoRoot2 = (opts) => opts.cwd ?? process.cwd();
149517
- async function loadScan(root, json2) {
149534
+ async function loadScan(root) {
149518
149535
  const cached = readScanState(root);
149519
149536
  if (cached) {
149520
149537
  return {
@@ -149522,16 +149539,6 @@ async function loadScan(root, json2) {
149522
149539
  decided: cached.decidedConflicts
149523
149540
  };
149524
149541
  }
149525
- if (json2) {
149526
- const { consolidate: consolidate2 } = await scanInProcess(root, {});
149527
- return {
149528
- open: consolidate2.merge.openConflicts,
149529
- decided: consolidate2.merge.decidedConflicts.map((d3) => ({
149530
- conflict: d3.conflict,
149531
- decision: d3.decision
149532
- }))
149533
- };
149534
- }
149535
149542
  const renderer = createStdoutStepRenderer();
149536
149543
  const tracker = new StepTracker(renderer.onProgress, SCAN_STEPS.map((s) => ({ ...s })));
149537
149544
  try {
@@ -149551,45 +149558,30 @@ async function loadScan(root, json2) {
149551
149558
  }
149552
149559
  async function runSpecConflictsList(opts = {}) {
149553
149560
  const root = repoRoot2(opts);
149554
- const scan = await loadScan(root, !!opts.json);
149561
+ const scan = await loadScan(root);
149555
149562
  const open = scan.open.map(serializeConflict);
149556
149563
  const decided = scan.decided.map((d3) => ({
149557
149564
  conflict: serializeConflict(d3.conflict),
149558
149565
  decision: d3.decision
149559
149566
  }));
149560
- if (opts.json) {
149561
- const payload = opts.all ? { openConflicts: open, decidedConflicts: decided } : opts.decided ? { decidedConflicts: decided } : { openConflicts: open };
149562
- process.stdout.write(JSON.stringify(payload, null, 2) + "\n");
149563
- return;
149564
- }
149565
149567
  mt("Conflicts");
149566
149568
  const which = opts.all ? "all" : opts.decided ? "decided" : "open";
149567
149569
  const list = opts.all ? [...open, ...decided.map((d3) => d3.conflict)] : opts.decided ? decided.map((d3) => d3.conflict) : open;
149568
149570
  O2.step(`${list.length} ${which} conflicts`);
149569
149571
  for (const c2 of list) {
149570
- O2.message(` \u2022 ${c2.id.slice(0, 12)}\u2026 [${c2.topic}] ${c2.subject} (${c2.candidates.length} candidates)`);
149572
+ O2.message(` \u2022 ${c2.id} [${c2.topic}] ${c2.subject} (${c2.candidates.length} candidates)`);
149571
149573
  }
149572
- gt("Use `truecourse spec conflicts show <id> --json` for full detail.");
149574
+ gt("Use `truecourse spec conflicts show <id>` for full detail.");
149573
149575
  }
149574
149576
  async function runSpecConflictsShow(conflictId2, opts = {}) {
149575
149577
  const root = repoRoot2(opts);
149576
- const scan = await loadScan(root, !!opts.json);
149578
+ const scan = await loadScan(root);
149577
149579
  const conflict = scan.open.find((c2) => c2.id === conflictId2) ?? scan.decided.find((d3) => d3.conflict.id === conflictId2)?.conflict;
149578
149580
  if (!conflict) {
149579
- if (opts.json) {
149580
- process.stdout.write(JSON.stringify({ ok: false, error: `conflict ${conflictId2} not found` }, null, 2) + "\n");
149581
- process.exit(1);
149582
- }
149583
149581
  pt(`Conflict ${conflictId2} not found.`);
149584
149582
  process.exit(1);
149585
149583
  }
149586
- if (opts.json) {
149587
- const payload = { ...serializeConflict(conflict) };
149588
- if (opts.diff) payload.fieldDifferences = computeFieldDifferences(conflict);
149589
- process.stdout.write(JSON.stringify(payload, null, 2) + "\n");
149590
- return;
149591
- }
149592
- mt(`Conflict ${conflict.id.slice(0, 12)}\u2026 \u2014 ${conflict.subject}`);
149584
+ mt(`Conflict ${conflict.id} \u2014 ${conflict.subject}`);
149593
149585
  O2.step(`topic: ${conflict.topic}`);
149594
149586
  if (conflict.explanation) O2.message(conflict.explanation);
149595
149587
  O2.step(`${conflict.candidates.length} candidates (default-pick: ${conflict.defaultPick})`);
@@ -149617,13 +149609,12 @@ async function runSpecConflictsShow(conflictId2, opts = {}) {
149617
149609
  }
149618
149610
  async function runSpecConflictsPick(conflictId2, candidateIndex, opts = {}) {
149619
149611
  const root = repoRoot2(opts);
149620
- const scan = await loadScan(root, !!opts.json);
149612
+ const scan = await loadScan(root);
149621
149613
  const conflict = scan.open.find((c2) => c2.id === conflictId2) ?? scan.decided.find((d3) => d3.conflict.id === conflictId2)?.conflict;
149622
- if (!conflict) return failNotFound(conflictId2, !!opts.json);
149614
+ if (!conflict) return failNotFound(conflictId2);
149623
149615
  if (!Number.isInteger(candidateIndex) || candidateIndex < 0 || candidateIndex >= conflict.candidates.length) {
149624
149616
  return fail(
149625
- `candidateIndex ${candidateIndex} out of range (0..${conflict.candidates.length - 1})`,
149626
- !!opts.json
149617
+ `candidateIndex ${candidateIndex} out of range (0..${conflict.candidates.length - 1})`
149627
149618
  );
149628
149619
  }
149629
149620
  upsertDecision(root, {
@@ -149632,36 +149623,30 @@ async function runSpecConflictsPick(conflictId2, candidateIndex, opts = {}) {
149632
149623
  candidateFingerprint: candidateFingerprint(conflict),
149633
149624
  note: opts.note
149634
149625
  });
149635
- await refreshScan(root, !!opts.json);
149636
- emitOk(`Picked candidate ${candidateIndex} on ${conflictId2.slice(0, 12)}\u2026`, !!opts.json, {
149637
- conflictId: conflictId2,
149638
- resolution: { kind: "pick", candidateIndex }
149639
- });
149626
+ await refreshScan(root);
149627
+ emitOk(`Picked candidate ${candidateIndex} on ${conflictId2.slice(0, 12)}\u2026`);
149640
149628
  }
149641
149629
  async function runSpecConflictsCustom(conflictId2, text, opts = {}) {
149642
149630
  const root = repoRoot2(opts);
149643
- const scan = await loadScan(root, !!opts.json);
149631
+ const scan = await loadScan(root);
149644
149632
  const conflict = scan.open.find((c2) => c2.id === conflictId2) ?? scan.decided.find((d3) => d3.conflict.id === conflictId2)?.conflict;
149645
- if (!conflict) return failNotFound(conflictId2, !!opts.json);
149633
+ if (!conflict) return failNotFound(conflictId2);
149646
149634
  if (!text || !text.trim()) {
149647
- return fail("--text must be a non-empty string", !!opts.json);
149635
+ return fail("--text must be a non-empty string");
149648
149636
  }
149649
149637
  upsertDecision(root, {
149650
149638
  conflictId: conflictId2,
149651
149639
  resolution: { kind: "custom", content: text },
149652
149640
  candidateFingerprint: candidateFingerprint(conflict)
149653
149641
  });
149654
- await refreshScan(root, !!opts.json);
149655
- emitOk(`Wrote custom answer for ${conflictId2.slice(0, 12)}\u2026`, !!opts.json, {
149656
- conflictId: conflictId2,
149657
- resolution: { kind: "custom" }
149658
- });
149642
+ await refreshScan(root);
149643
+ emitOk(`Wrote custom answer for ${conflictId2.slice(0, 12)}\u2026`);
149659
149644
  }
149660
149645
  async function runSpecConflictsRevoke(conflictId2, opts = {}) {
149661
149646
  const root = repoRoot2(opts);
149662
149647
  revokeDecision(root, conflictId2);
149663
- await refreshScan(root, !!opts.json);
149664
- emitOk(`Revoked decision for ${conflictId2.slice(0, 12)}\u2026`, !!opts.json, { conflictId: conflictId2 });
149648
+ await refreshScan(root);
149649
+ emitOk(`Revoked decision for ${conflictId2.slice(0, 12)}\u2026`);
149665
149650
  }
149666
149651
  function serializeConflict(c2) {
149667
149652
  return {
@@ -149669,30 +149654,18 @@ function serializeConflict(c2) {
149669
149654
  candidateFingerprint: candidateFingerprint(c2)
149670
149655
  };
149671
149656
  }
149672
- async function refreshScan(root, json2) {
149673
- if (json2) {
149674
- await scanInProcess(root, {});
149675
- return;
149676
- }
149657
+ async function refreshScan(root) {
149677
149658
  await scanInProcess(root, {});
149678
149659
  }
149679
- function emitOk(msg, json2, payload) {
149680
- if (json2) {
149681
- process.stdout.write(JSON.stringify({ ok: true, ...payload }, null, 2) + "\n");
149682
- return;
149683
- }
149660
+ function emitOk(msg) {
149684
149661
  gt(msg);
149685
149662
  }
149686
- function fail(msg, json2) {
149687
- if (json2) {
149688
- process.stdout.write(JSON.stringify({ ok: false, error: msg }, null, 2) + "\n");
149689
- process.exit(1);
149690
- }
149663
+ function fail(msg) {
149691
149664
  pt(msg);
149692
149665
  process.exit(1);
149693
149666
  }
149694
- function failNotFound(id, json2) {
149695
- return fail(`conflict ${id} not found`, json2);
149667
+ function failNotFound(id) {
149668
+ return fail(`conflict ${id} not found`);
149696
149669
  }
149697
149670
  function computeFieldDifferences(conflict) {
149698
149671
  const out = [];
@@ -149761,10 +149734,6 @@ async function runSpecChainsList(opts = {}) {
149761
149734
  const root = repoRoot3(opts);
149762
149735
  const decisions = readDecisions(root);
149763
149736
  const manual = decisions.manualChains ?? [];
149764
- if (opts.json) {
149765
- process.stdout.write(JSON.stringify({ manual }, null, 2) + "\n");
149766
- return;
149767
- }
149768
149737
  mt("Manual chains");
149769
149738
  if (manual.length === 0) O2.step("(none)");
149770
149739
  for (const c2 of manual) {
@@ -149774,35 +149743,21 @@ async function runSpecChainsList(opts = {}) {
149774
149743
  }
149775
149744
  async function runSpecChainsAdd(opts) {
149776
149745
  const root = repoRoot3(opts);
149777
- if (opts.older === opts.newer) return fail2("older and newer must be different docs", !!opts.json);
149746
+ if (opts.older === opts.newer) return fail2("older and newer must be different docs");
149778
149747
  addManualChain(root, { older: opts.older, newer: opts.newer, note: opts.note });
149779
149748
  await scanInProcess(root, {});
149780
- emitOk2(`Marked ${opts.older} as superseded by ${opts.newer}`, !!opts.json, {
149781
- older: opts.older,
149782
- newer: opts.newer
149783
- });
149749
+ emitOk2(`Marked ${opts.older} as superseded by ${opts.newer}`);
149784
149750
  }
149785
149751
  async function runSpecChainsRemove(opts) {
149786
149752
  const root = repoRoot3(opts);
149787
149753
  removeManualChain(root, { older: opts.older, newer: opts.newer });
149788
149754
  await scanInProcess(root, {});
149789
- emitOk2(`Removed chain ${opts.older} \u2192 ${opts.newer}`, !!opts.json, {
149790
- older: opts.older,
149791
- newer: opts.newer
149792
- });
149755
+ emitOk2(`Removed chain ${opts.older} \u2192 ${opts.newer}`);
149793
149756
  }
149794
- function emitOk2(msg, json2, payload) {
149795
- if (json2) {
149796
- process.stdout.write(JSON.stringify({ ok: true, ...payload }, null, 2) + "\n");
149797
- return;
149798
- }
149757
+ function emitOk2(msg) {
149799
149758
  gt(msg);
149800
149759
  }
149801
- function fail2(msg, json2) {
149802
- if (json2) {
149803
- process.stdout.write(JSON.stringify({ ok: false, error: msg }, null, 2) + "\n");
149804
- process.exit(1);
149805
- }
149760
+ function fail2(msg) {
149806
149761
  pt(msg);
149807
149762
  process.exit(1);
149808
149763
  }
@@ -149816,10 +149771,6 @@ async function runSpecDocsSkipped(opts = {}) {
149816
149771
  const decisions = readDecisions(root);
149817
149772
  const skipped = scan?.skippedDocs ?? [];
149818
149773
  const manualIncludes = decisions.manualIncludes ?? [];
149819
- if (opts.json) {
149820
- process.stdout.write(JSON.stringify({ skipped, manualIncludes }, null, 2) + "\n");
149821
- return;
149822
- }
149823
149774
  mt("Skipped docs");
149824
149775
  if (skipped.length === 0) O2.step("(none)");
149825
149776
  for (const s of skipped) {
@@ -149835,30 +149786,22 @@ async function runSpecDocsSkipped(opts = {}) {
149835
149786
  }
149836
149787
  async function runSpecDocsInclude(docPath, opts = {}) {
149837
149788
  const root = repoRoot4(opts);
149838
- if (!docPath) return fail3("Missing doc path", !!opts.json);
149789
+ if (!docPath) return fail3("Missing doc path");
149839
149790
  addManualInclude(root, docPath);
149840
149791
  await scanInProcess(root, {});
149841
- emitOk3(`Force-include ${docPath}`, !!opts.json, { path: docPath });
149792
+ emitOk3(`Force-include ${docPath}`);
149842
149793
  }
149843
149794
  async function runSpecDocsUninclude(docPath, opts = {}) {
149844
149795
  const root = repoRoot4(opts);
149845
- if (!docPath) return fail3("Missing doc path", !!opts.json);
149796
+ if (!docPath) return fail3("Missing doc path");
149846
149797
  removeManualInclude(root, docPath);
149847
149798
  await scanInProcess(root, {});
149848
- emitOk3(`Removed force-include for ${docPath}`, !!opts.json, { path: docPath });
149799
+ emitOk3(`Removed force-include for ${docPath}`);
149849
149800
  }
149850
- function emitOk3(msg, json2, payload) {
149851
- if (json2) {
149852
- process.stdout.write(JSON.stringify({ ok: true, ...payload }, null, 2) + "\n");
149853
- return;
149854
- }
149801
+ function emitOk3(msg) {
149855
149802
  gt(msg);
149856
149803
  }
149857
- function fail3(msg, json2) {
149858
- if (json2) {
149859
- process.stdout.write(JSON.stringify({ ok: false, error: msg }, null, 2) + "\n");
149860
- process.exit(1);
149861
- }
149804
+ function fail3(msg) {
149862
149805
  pt(msg);
149863
149806
  process.exit(1);
149864
149807
  }
@@ -149887,26 +149830,6 @@ var SOURCE_LABEL = {
149887
149830
  async function runConfigLlmShow(options = {}) {
149888
149831
  const repoRoot5 = options.cwd ?? process.cwd();
149889
149832
  const { stages, fallbackModel } = describeStageResolutions(repoRoot5);
149890
- if (options.json) {
149891
- process.stdout.write(
149892
- JSON.stringify(
149893
- {
149894
- repoRoot: path56.relative(process.cwd(), repoRoot5) || ".",
149895
- stages: stages.map((s) => ({
149896
- stageId: s.stageId,
149897
- effectiveModel: s.effectiveModel,
149898
- defaultModel: STAGE_DEFAULTS[s.stageId],
149899
- source: s.source,
149900
- envVar: s.envVar ?? null
149901
- })),
149902
- fallbackModel
149903
- },
149904
- null,
149905
- 2
149906
- ) + "\n"
149907
- );
149908
- return;
149909
- }
149910
149833
  mt("LLM model resolution");
149911
149834
  O2.info(`repoRoot ${path56.relative(process.cwd(), repoRoot5) || "."}`);
149912
149835
  O2.info(`fallback ${fallbackModel ?? "(not configured)"}`);
@@ -152828,7 +152751,7 @@ async function runHooksRun() {
152828
152751
 
152829
152752
  // tools/cli/src/index.ts
152830
152753
  var program2 = new Command();
152831
- program2.name("truecourse").version("0.6.0-next.0").description("TrueCourse CLI \u2014 analyze your repository and open the dashboard");
152754
+ program2.name("truecourse").version("0.6.0-next.2").description("TrueCourse CLI \u2014 analyze your repository and open the dashboard");
152832
152755
  var dashboardCmd = program2.command("dashboard").description("Start the TrueCourse dashboard and open it in your browser").option("--reconfigure", "Re-prompt for console vs background service mode").option("--service", "Run as a background service (skips mode prompt)").option("--console", "Run in this terminal (skips mode prompt)").action(async (options) => {
152833
152756
  if (options.service && options.console) {
152834
152757
  console.error("error: --service and --console are mutually exclusive");
@@ -152902,55 +152825,52 @@ specCmd.command("status").description("Summary of docs, claims, modules, and pen
152902
152825
  await runSpecStatus();
152903
152826
  });
152904
152827
  var conflictsCmd = specCmd.command("conflicts").description("Inspect and resolve open / decided conflicts (agent-friendly)");
152905
- conflictsCmd.command("list").description("List conflicts (open by default; --decided or --all to widen)").option("--json", "Emit a JSON document on stdout for agent consumption").option("--decided", "Show decided conflicts instead of open").option("--all", "Show both open and decided conflicts").action(async (opts) => {
152906
- await runSpecConflictsList({ json: !!opts.json, decided: !!opts.decided, all: !!opts.all });
152828
+ conflictsCmd.command("list").description("List conflicts (open by default; --decided or --all to widen)").option("--decided", "Show decided conflicts instead of open").option("--all", "Show both open and decided conflicts").action(async (opts) => {
152829
+ await runSpecConflictsList({ decided: !!opts.decided, all: !!opts.all });
152907
152830
  });
152908
- conflictsCmd.command("show <id>").description("Show full detail for one conflict").option("--json", "Emit a JSON document on stdout for agent consumption").option(
152831
+ conflictsCmd.command("show <id>").description("Show full detail for one conflict").option(
152909
152832
  "--diff",
152910
152833
  "Include precomputed field-level diffs (paths + values) between candidates"
152911
152834
  ).action(async (id, opts) => {
152912
- await runSpecConflictsShow(id, { json: !!opts.json, diff: !!opts.diff });
152835
+ await runSpecConflictsShow(id, { diff: !!opts.diff });
152913
152836
  });
152914
- conflictsCmd.command("pick <id> <candidateIndex>").description("Resolve a conflict by picking one of its candidates").option("--note <text>", "Optional human-readable rationale").option("--json", "Emit a JSON document on stdout for agent consumption").action(async (id, idx, opts) => {
152837
+ conflictsCmd.command("pick <id> <candidateIndex>").description("Resolve a conflict by picking one of its candidates").option("--note <text>", "Optional human-readable rationale").action(async (id, idx, opts) => {
152915
152838
  await runSpecConflictsPick(id, parseInt(idx, 10), {
152916
- note: opts.note,
152917
- json: !!opts.json
152839
+ note: opts.note
152918
152840
  });
152919
152841
  });
152920
- conflictsCmd.command("custom <id>").description("Resolve a conflict with a free-text custom answer").requiredOption("--text <text>", "The authoritative content for this subject").option("--json", "Emit a JSON document on stdout for agent consumption").action(async (id, opts) => {
152921
- await runSpecConflictsCustom(id, opts.text, { json: !!opts.json });
152842
+ conflictsCmd.command("custom <id>").description("Resolve a conflict with a free-text custom answer").requiredOption("--text <text>", "The authoritative content for this subject").action(async (id, opts) => {
152843
+ await runSpecConflictsCustom(id, opts.text);
152922
152844
  });
152923
- conflictsCmd.command("revoke <id>").description("Remove a previously-saved decision (the conflict re-opens)").option("--json", "Emit a JSON document on stdout for agent consumption").action(async (id, opts) => {
152924
- await runSpecConflictsRevoke(id, { json: !!opts.json });
152845
+ conflictsCmd.command("revoke <id>").description("Remove a previously-saved decision (the conflict re-opens)").action(async (id) => {
152846
+ await runSpecConflictsRevoke(id);
152925
152847
  });
152926
152848
  var chainsCmd = specCmd.command("chains").description("Manage manual version chains (supersession overrides)");
152927
- chainsCmd.command("list").description("List manual chains").option("--json", "Emit a JSON document on stdout for agent consumption").action(async (opts) => {
152928
- await runSpecChainsList({ json: !!opts.json });
152849
+ chainsCmd.command("list").description("List manual chains").action(async () => {
152850
+ await runSpecChainsList();
152929
152851
  });
152930
- chainsCmd.command("add").description("Mark `older` as superseded by `newer`").requiredOption("--older <path>", "Repo-relative path of the older doc").requiredOption("--newer <path>", "Repo-relative path of the newer doc").option("--note <text>", "Optional rationale").option("--json", "Emit a JSON document on stdout for agent consumption").action(async (opts) => {
152852
+ chainsCmd.command("add").description("Mark `older` as superseded by `newer`").requiredOption("--older <path>", "Repo-relative path of the older doc").requiredOption("--newer <path>", "Repo-relative path of the newer doc").option("--note <text>", "Optional rationale").action(async (opts) => {
152931
152853
  await runSpecChainsAdd({
152932
152854
  older: opts.older,
152933
152855
  newer: opts.newer,
152934
- note: opts.note,
152935
- json: !!opts.json
152856
+ note: opts.note
152936
152857
  });
152937
152858
  });
152938
- chainsCmd.command("remove").description("Remove a manual chain").requiredOption("--older <path>", "Repo-relative path of the older doc").requiredOption("--newer <path>", "Repo-relative path of the newer doc").option("--json", "Emit a JSON document on stdout for agent consumption").action(async (opts) => {
152859
+ chainsCmd.command("remove").description("Remove a manual chain").requiredOption("--older <path>", "Repo-relative path of the older doc").requiredOption("--newer <path>", "Repo-relative path of the newer doc").action(async (opts) => {
152939
152860
  await runSpecChainsRemove({
152940
152861
  older: opts.older,
152941
- newer: opts.newer,
152942
- json: !!opts.json
152862
+ newer: opts.newer
152943
152863
  });
152944
152864
  });
152945
152865
  var docsCmd = specCmd.command("docs").description("Manage LLM relevance-filter overrides (skipped docs)");
152946
- docsCmd.command("skipped").description("List docs the relevance filter excluded from extraction").option("--json", "Emit a JSON document on stdout for agent consumption").action(async (opts) => {
152947
- await runSpecDocsSkipped({ json: !!opts.json });
152866
+ docsCmd.command("skipped").description("List docs the relevance filter excluded from extraction").action(async () => {
152867
+ await runSpecDocsSkipped();
152948
152868
  });
152949
- docsCmd.command("include <path>").description("Force-include a skipped doc and re-scan").option("--json", "Emit a JSON document on stdout for agent consumption").action(async (docPath, opts) => {
152950
- await runSpecDocsInclude(docPath, { json: !!opts.json });
152869
+ docsCmd.command("include <path>").description("Force-include a skipped doc and re-scan").action(async (docPath) => {
152870
+ await runSpecDocsInclude(docPath);
152951
152871
  });
152952
- docsCmd.command("uninclude <path>").description("Remove a force-include override").option("--json", "Emit a JSON document on stdout for agent consumption").action(async (docPath, opts) => {
152953
- await runSpecDocsUninclude(docPath, { json: !!opts.json });
152872
+ docsCmd.command("uninclude <path>").description("Remove a force-include override").action(async (docPath) => {
152873
+ await runSpecDocsUninclude(docPath);
152954
152874
  });
152955
152875
  program2.command("verify").description("Compare code against the canonical TC contracts").option("--code-dir <path>", "Override the code directory (default: auto-detect)").option("--diff", "Diff current drifts against the committed LATEST baseline").option("--stash", "Pre-approve stashing pending changes (verify committed state)").option("--no-stash", "Verify the working tree as-is without stashing").action(async (options) => {
152956
152876
  await runVerify({ codeDir: options.codeDir, diff: options.diff, stash: options.stash });
@@ -152979,8 +152899,8 @@ rulesCmd.command("reset [ruleKey]").description("Clear per-rule overrides (one r
152979
152899
  });
152980
152900
  var configCmd = program2.command("config").description("Inspect per-repo TrueCourse configuration");
152981
152901
  var configLlmCmd = configCmd.command("llm").description("LLM model configuration for the current repo");
152982
- configLlmCmd.command("show").description("Print the effective model resolution for every pipeline stage").option("--json", "Emit a single JSON document").action(async (options) => {
152983
- await runConfigLlmShow({ json: !!options.json });
152902
+ configLlmCmd.command("show").description("Print the effective model resolution for every pipeline stage").action(async () => {
152903
+ await runConfigLlmShow();
152984
152904
  });
152985
152905
  var telemetryCmd = program2.command("telemetry").description("Manage anonymous usage telemetry");
152986
152906
  telemetryCmd.command("enable").description("Enable anonymous usage telemetry").action(() => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "truecourse",
3
- "version": "0.6.0-next.0",
3
+ "version": "0.6.0-next.2",
4
4
  "description": "Visualize your codebase architecture as an interactive graph",
5
5
  "type": "module",
6
6
  "bin": {