cherry-works 0.7.1 → 0.7.4

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/main.js CHANGED
@@ -9507,7 +9507,7 @@ var require_core = __commonJS({
9507
9507
  errorsText(errors = this.errors, { separator = ", ", dataVar = "data" } = {}) {
9508
9508
  if (!errors || errors.length === 0)
9509
9509
  return "No errors";
9510
- return errors.map((e) => `${dataVar}${e.instancePath} ${e.message}`).reduce((text, msg) => text + separator + msg);
9510
+ return errors.map((e) => `${dataVar}${e.instancePath} ${e.message}`).reduce((text2, msg) => text2 + separator + msg);
9511
9511
  }
9512
9512
  $dataMetaSchema(metaSchema, keywordsJsonPointers) {
9513
9513
  const rules = this.RULES.all;
@@ -14822,14 +14822,14 @@ var require_foldFlowLines = __commonJS({
14822
14822
  var FOLD_FLOW = "flow";
14823
14823
  var FOLD_BLOCK = "block";
14824
14824
  var FOLD_QUOTED = "quoted";
14825
- function foldFlowLines(text, indent, mode = "flow", { indentAtStart, lineWidth = 80, minContentWidth = 20, onFold, onOverflow } = {}) {
14825
+ function foldFlowLines(text2, indent, mode = "flow", { indentAtStart, lineWidth = 80, minContentWidth = 20, onFold, onOverflow } = {}) {
14826
14826
  if (!lineWidth || lineWidth < 0)
14827
- return text;
14827
+ return text2;
14828
14828
  if (lineWidth < minContentWidth)
14829
14829
  minContentWidth = 0;
14830
14830
  const endStep = Math.max(1 + minContentWidth, 1 + lineWidth - indent.length);
14831
- if (text.length <= endStep)
14832
- return text;
14831
+ if (text2.length <= endStep)
14832
+ return text2;
14833
14833
  const folds = [];
14834
14834
  const escapedFolds = {};
14835
14835
  let end = lineWidth - indent.length;
@@ -14846,14 +14846,14 @@ var require_foldFlowLines = __commonJS({
14846
14846
  let escStart = -1;
14847
14847
  let escEnd = -1;
14848
14848
  if (mode === FOLD_BLOCK) {
14849
- i = consumeMoreIndentedLines(text, i, indent.length);
14849
+ i = consumeMoreIndentedLines(text2, i, indent.length);
14850
14850
  if (i !== -1)
14851
14851
  end = i + endStep;
14852
14852
  }
14853
- for (let ch; ch = text[i += 1]; ) {
14853
+ for (let ch; ch = text2[i += 1]; ) {
14854
14854
  if (mode === FOLD_QUOTED && ch === "\\") {
14855
14855
  escStart = i;
14856
- switch (text[i + 1]) {
14856
+ switch (text2[i + 1]) {
14857
14857
  case "x":
14858
14858
  i += 3;
14859
14859
  break;
@@ -14870,12 +14870,12 @@ var require_foldFlowLines = __commonJS({
14870
14870
  }
14871
14871
  if (ch === "\n") {
14872
14872
  if (mode === FOLD_BLOCK)
14873
- i = consumeMoreIndentedLines(text, i, indent.length);
14873
+ i = consumeMoreIndentedLines(text2, i, indent.length);
14874
14874
  end = i + indent.length + endStep;
14875
14875
  split = void 0;
14876
14876
  } else {
14877
14877
  if (ch === " " && prev && prev !== " " && prev !== "\n" && prev !== " ") {
14878
- const next = text[i + 1];
14878
+ const next = text2[i + 1];
14879
14879
  if (next && next !== " " && next !== "\n" && next !== " ")
14880
14880
  split = i;
14881
14881
  }
@@ -14887,12 +14887,12 @@ var require_foldFlowLines = __commonJS({
14887
14887
  } else if (mode === FOLD_QUOTED) {
14888
14888
  while (prev === " " || prev === " ") {
14889
14889
  prev = ch;
14890
- ch = text[i += 1];
14890
+ ch = text2[i += 1];
14891
14891
  overflow = true;
14892
14892
  }
14893
14893
  const j = i > escEnd + 1 ? i - 2 : escStart - 1;
14894
14894
  if (escapedFolds[j])
14895
- return text;
14895
+ return text2;
14896
14896
  folds.push(j);
14897
14897
  escapedFolds[j] = true;
14898
14898
  end = j + endStep;
@@ -14907,39 +14907,39 @@ var require_foldFlowLines = __commonJS({
14907
14907
  if (overflow && onOverflow)
14908
14908
  onOverflow();
14909
14909
  if (folds.length === 0)
14910
- return text;
14910
+ return text2;
14911
14911
  if (onFold)
14912
14912
  onFold();
14913
- let res = text.slice(0, folds[0]);
14913
+ let res = text2.slice(0, folds[0]);
14914
14914
  for (let i2 = 0; i2 < folds.length; ++i2) {
14915
14915
  const fold = folds[i2];
14916
- const end2 = folds[i2 + 1] || text.length;
14916
+ const end2 = folds[i2 + 1] || text2.length;
14917
14917
  if (fold === 0)
14918
14918
  res = `
14919
- ${indent}${text.slice(0, end2)}`;
14919
+ ${indent}${text2.slice(0, end2)}`;
14920
14920
  else {
14921
14921
  if (mode === FOLD_QUOTED && escapedFolds[fold])
14922
- res += `${text[fold]}\\`;
14922
+ res += `${text2[fold]}\\`;
14923
14923
  res += `
14924
- ${indent}${text.slice(fold + 1, end2)}`;
14924
+ ${indent}${text2.slice(fold + 1, end2)}`;
14925
14925
  }
14926
14926
  }
14927
14927
  return res;
14928
14928
  }
14929
- function consumeMoreIndentedLines(text, i, indent) {
14929
+ function consumeMoreIndentedLines(text2, i, indent) {
14930
14930
  let end = i;
14931
14931
  let start = i + 1;
14932
- let ch = text[start];
14932
+ let ch = text2[start];
14933
14933
  while (ch === " " || ch === " ") {
14934
14934
  if (i < start + indent) {
14935
- ch = text[++i];
14935
+ ch = text2[++i];
14936
14936
  } else {
14937
14937
  do {
14938
- ch = text[++i];
14938
+ ch = text2[++i];
14939
14939
  } while (ch && ch !== "\n");
14940
14940
  end = i;
14941
14941
  start = i + 1;
14942
- ch = text[start];
14942
+ ch = text2[start];
14943
14943
  }
14944
14944
  }
14945
14945
  return end;
@@ -21665,7 +21665,7 @@ var require_cross_spawn = __commonJS({
21665
21665
  var cp = __require("child_process");
21666
21666
  var parse5 = require_parse2();
21667
21667
  var enoent = require_enoent();
21668
- function spawn5(command2, args, options) {
21668
+ function spawn6(command2, args, options) {
21669
21669
  const parsed = parse5(command2, args, options);
21670
21670
  const spawned = cp.spawn(parsed.command, parsed.args, parsed.options);
21671
21671
  enoent.hookChildProcess(spawned, parsed);
@@ -21677,8 +21677,8 @@ var require_cross_spawn = __commonJS({
21677
21677
  result.error = result.error || enoent.verifyENOENTSync(result.status, parsed);
21678
21678
  return result;
21679
21679
  }
21680
- module.exports = spawn5;
21681
- module.exports.spawn = spawn5;
21680
+ module.exports = spawn6;
21681
+ module.exports.spawn = spawn6;
21682
21682
  module.exports.sync = spawnSync;
21683
21683
  module.exports._parse = parse5;
21684
21684
  module.exports._enoent = enoent;
@@ -21898,7 +21898,7 @@ import { pathToFileURL as pathToFileURL2 } from "url";
21898
21898
  // package.json
21899
21899
  var package_default = {
21900
21900
  name: "cherry-works",
21901
- version: "0.7.1",
21901
+ version: "0.7.4",
21902
21902
  description: "The charter engine: resolves a charter and compiles it into what a coding agent reads.",
21903
21903
  keywords: [
21904
21904
  "claude-code",
@@ -22057,10 +22057,10 @@ var UI = class {
22057
22057
  });
22058
22058
  return this.rows[this.rows.length - 1];
22059
22059
  }
22060
- colFromString(text) {
22060
+ colFromString(text2) {
22061
22061
  return {
22062
- text,
22063
- padding: this.measurePadding(text)
22062
+ text: text2,
22063
+ padding: this.measurePadding(text2)
22064
22064
  };
22065
22065
  }
22066
22066
  measurePadding(str) {
@@ -25324,17 +25324,17 @@ function usage(yargs, shim3) {
25324
25324
  };
25325
25325
  return self;
25326
25326
  }
25327
- function isIndentedText(text) {
25328
- return typeof text === "object";
25327
+ function isIndentedText(text2) {
25328
+ return typeof text2 === "object";
25329
25329
  }
25330
- function addIndentation(text, indent) {
25331
- return isIndentedText(text) ? { text: text.text, indentation: text.indentation + indent } : { text, indentation: indent };
25330
+ function addIndentation(text2, indent) {
25331
+ return isIndentedText(text2) ? { text: text2.text, indentation: text2.indentation + indent } : { text: text2, indentation: indent };
25332
25332
  }
25333
- function getIndentation(text) {
25334
- return isIndentedText(text) ? text.indentation : 0;
25333
+ function getIndentation(text2) {
25334
+ return isIndentedText(text2) ? text2.indentation : 0;
25335
25335
  }
25336
- function getText(text) {
25337
- return isIndentedText(text) ? text.text : text;
25336
+ function getText(text2) {
25337
+ return isIndentedText(text2) ? text2.text : text2;
25338
25338
  }
25339
25339
 
25340
25340
  // node_modules/.pnpm/yargs@18.1.0/node_modules/yargs/build/lib/completion-templates.js
@@ -37577,8 +37577,8 @@ function ko_default() {
37577
37577
  }
37578
37578
 
37579
37579
  // node_modules/.pnpm/zod@4.6.1/node_modules/zod/v4/locales/lt.js
37580
- var capitalizeFirstCharacter = (text) => {
37581
- return text.charAt(0).toUpperCase() + text.slice(1);
37580
+ var capitalizeFirstCharacter = (text2) => {
37581
+ return text2.charAt(0).toUpperCase() + text2.slice(1);
37582
37582
  };
37583
37583
  function getUnitTypeFromNumber(number4) {
37584
37584
  const abs = Math.abs(number4);
@@ -51930,7 +51930,7 @@ var HonoRequest = class {
51930
51930
  * ```
51931
51931
  */
51932
51932
  json() {
51933
- return this.#cachedBody("text").then((text) => JSON.parse(text));
51933
+ return this.#cachedBody("text").then((text2) => JSON.parse(text2));
51934
51934
  }
51935
51935
  /**
51936
51936
  * `.text()` can parse Request body of type `text/plain`
@@ -52496,9 +52496,9 @@ var Context = class {
52496
52496
  * })
52497
52497
  * ```
52498
52498
  */
52499
- text = (text, arg, headers) => {
52500
- return !this.#preparedHeaders && !this.#status && !arg && !headers && !this.finalized ? new Response(text) : this.#newResponse(
52501
- text,
52499
+ text = (text2, arg, headers) => {
52500
+ return !this.#preparedHeaders && !this.#status && !arg && !headers && !this.finalized ? new Response(text2) : this.#newResponse(
52501
+ text2,
52502
52502
  arg,
52503
52503
  setDefaultContentType(TEXT_PLAIN, headers)
52504
52504
  );
@@ -57515,7 +57515,15 @@ var SessionReviewOutcomeSchema = dto(
57515
57515
  dailySessionSummary: external_exports.record(external_exports.string(), DataDTOs.SessionSummary)
57516
57516
  })
57517
57517
  );
57518
- var OutcomeDTOs = byType(DoctorOutcomeSchema, ExplanationOutcomeSchema, SessionReviewOutcomeSchema);
57518
+ var SensorRunOutcomeSchema = dto(
57519
+ "SensorRunOutcome",
57520
+ external_exports.object({
57521
+ exitCode: external_exports.number(),
57522
+ answer: external_exports.string(),
57523
+ problem: external_exports.string()
57524
+ })
57525
+ );
57526
+ var OutcomeDTOs = byType(DoctorOutcomeSchema, ExplanationOutcomeSchema, SensorRunOutcomeSchema, SessionReviewOutcomeSchema);
57519
57527
 
57520
57528
  // src/hexagon/domain/models/helper.ts
57521
57529
  function formatFrontmatterValue(value) {
@@ -57837,10 +57845,10 @@ var SAMPLE_CASES = [
57837
57845
  var SAMPLE = JSON.stringify({ cases: SAMPLE_CASES }, void 0, 1).replace(/\n\s*/g, " ");
57838
57846
  var DEFAULT_TEST_SUITE_BODY = `${JSON.stringify({ description: "What these cases pin down.", cases: [SAMPLE_CASES[0]] }, null, 2)}
57839
57847
  `;
57840
- function testSuiteOf(text) {
57848
+ function testSuiteOf(text2) {
57841
57849
  let written;
57842
57850
  try {
57843
- written = JSON.parse(text);
57851
+ written = JSON.parse(text2);
57844
57852
  } catch {
57845
57853
  throw new TestSuiteFault(
57846
57854
  `This file is not JSON, so nothing can read the cases it was meant to hold.`,
@@ -57849,7 +57857,7 @@ function testSuiteOf(text) {
57849
57857
  }
57850
57858
  const read = TestSuiteSchema2.safeParse(written);
57851
57859
  if (!read.success) throw new TestSuiteFault(`This file is not written as a suite of cases.`, `Write it as ${SAMPLE}`);
57852
- return new TestSuite(read.data.description, read.data.cases, text);
57860
+ return new TestSuite(read.data.description, read.data.cases, text2);
57853
57861
  }
57854
57862
 
57855
57863
  // src/hexagon/domain/models/test/TestRoot.ts
@@ -58075,6 +58083,9 @@ function sessionReviewOutcomeDTO(sessionAnalysis, sessionAnalysisSummary, sessio
58075
58083
  }
58076
58084
  };
58077
58085
  }
58086
+ function sensorRunOutcomeDTO(signalAnswer) {
58087
+ return { type: "SensorRunOutcome", data: { exitCode: signalAnswer.exitCode, answer: signalAnswer.stdout, problem: signalAnswer.stderr } };
58088
+ }
58078
58089
 
58079
58090
  // src/driver/portal/routes.ts
58080
58091
  var json3 = (schema, description) => ({
@@ -58514,8 +58525,27 @@ var RemoveCommand = class {
58514
58525
  }
58515
58526
  };
58516
58527
 
58517
- // src/driver/cli/commands/SessionsCommand.ts
58528
+ // src/driver/cli/commands/SensorRunCommand.ts
58529
+ import { text } from "stream/consumers";
58518
58530
  var OPTIONS12 = {
58531
+ signal: {
58532
+ type: "string",
58533
+ describe: "The signal the host fired, as a sensor names it: Stop, PreToolUse\u2026"
58534
+ }
58535
+ };
58536
+ var SensorRunCommand = class {
58537
+ name = "sensor run <signal>";
58538
+ summary = "Run every sensor of a signal, as the host's one hook for it";
58539
+ options = OPTIONS12;
58540
+ async run({ sensorRunningApp: sensorRunningApp2 }, { signal }) {
58541
+ const stdin = process.stdin.isTTY ? "" : await text(process.stdin);
58542
+ const { data: sensorRunOutcome } = await sensorRunningApp2.runSensors(signal ?? "", stdin);
58543
+ return { code: sensorRunOutcome.exitCode, result: sensorRunOutcome.answer, problem: sensorRunOutcome.problem };
58544
+ }
58545
+ };
58546
+
58547
+ // src/driver/cli/commands/SessionsCommand.ts
58548
+ var OPTIONS13 = {
58519
58549
  since: {
58520
58550
  type: "string",
58521
58551
  describe: "Count the sessions whose last stop is on or after this day, YYYY-MM-DD; 31 days from it unless --until says"
@@ -58533,7 +58563,7 @@ var OPTIONS12 = {
58533
58563
  var SessionsCommand = class {
58534
58564
  name = "sessions";
58535
58565
  summary = "Sum up the tokens of the sessions kept on this machine, by day and by session";
58536
- options = OPTIONS12;
58566
+ options = OPTIONS13;
58537
58567
  async run({ sessionReviewingApp: sessionReviewingApp2 }, { since, until, json: isJson }) {
58538
58568
  const sessionReviewOutcome = await sessionReviewingApp2.sessionSummary(since, until);
58539
58569
  if (isJson) return { code: EXIT_OK, result: `${JSON.stringify(sessionReviewOutcome, null, 2)}
@@ -58591,7 +58621,7 @@ var SuiteAddCommand = class {
58591
58621
  };
58592
58622
 
58593
58623
  // src/driver/cli/commands/SuiteEditCommand.ts
58594
- var OPTIONS13 = {
58624
+ var OPTIONS14 = {
58595
58625
  name: {
58596
58626
  type: "string",
58597
58627
  describe: `The test file's name under ${TEST_DIRECTORY}/: "untitled-1.json"`
@@ -58600,7 +58630,7 @@ var OPTIONS13 = {
58600
58630
  var SuiteEditCommand = class {
58601
58631
  name = "suite edit <name>";
58602
58632
  summary = "Open one test file in your editor";
58603
- options = OPTIONS13;
58633
+ options = OPTIONS14;
58604
58634
  async run({ cwd, testAuthoringApp: testAuthoringApp2 }, { name }) {
58605
58635
  const { testSuites } = (await testAuthoringApp2.suites()).data;
58606
58636
  if (!testSuites.some((one) => one.data.name === name))
@@ -58613,7 +58643,7 @@ var SuiteEditCommand = class {
58613
58643
  };
58614
58644
 
58615
58645
  // src/driver/cli/commands/SuiteRemoveCommand.ts
58616
- var OPTIONS14 = {
58646
+ var OPTIONS15 = {
58617
58647
  name: {
58618
58648
  type: "string",
58619
58649
  describe: `The test file's name under ${TEST_DIRECTORY}/: "untitled-1.json"`
@@ -58622,7 +58652,7 @@ var OPTIONS14 = {
58622
58652
  var SuiteRemoveCommand = class {
58623
58653
  name = "suite remove <name>";
58624
58654
  summary = "Delete one test file";
58625
- options = OPTIONS14;
58655
+ options = OPTIONS15;
58626
58656
  async run({ testAuthoringApp: testAuthoringApp2 }, { name }) {
58627
58657
  const removedName = await testAuthoringApp2.removeSuite(name ?? "");
58628
58658
  return { code: EXIT_OK, result: `Removed ${TEST_DIRECTORY}/${removedName}.
@@ -58669,7 +58699,7 @@ function lines2(one) {
58669
58699
  }
58670
58700
 
58671
58701
  // src/driver/cli/commands/VendorAddCommand.ts
58672
- var OPTIONS15 = {
58702
+ var OPTIONS16 = {
58673
58703
  source: {
58674
58704
  type: "string",
58675
58705
  describe: "What git clones the charter from: an address over any transport, or a path on disk"
@@ -58682,7 +58712,7 @@ var OPTIONS15 = {
58682
58712
  var VendorAddCommand = class {
58683
58713
  name = "vendor add <source>";
58684
58714
  summary = "Install a charter from a git source, or bring an installed one up to date";
58685
- options = OPTIONS15;
58715
+ options = OPTIONS16;
58686
58716
  async run({ charterVendoringApp: charterVendoringApp2 }, { source, ref }) {
58687
58717
  const folder = await charterVendoringApp2.add(source ?? "", ref);
58688
58718
  return {
@@ -58710,7 +58740,7 @@ var VendorListCommand = class {
58710
58740
  };
58711
58741
 
58712
58742
  // src/driver/cli/commands/VendorRemoveCommand.ts
58713
- var OPTIONS16 = {
58743
+ var OPTIONS17 = {
58714
58744
  name: {
58715
58745
  type: "string",
58716
58746
  describe: "The folder this charter was installed as, as it reads under .cw/vendor/"
@@ -58719,7 +58749,7 @@ var OPTIONS16 = {
58719
58749
  var VendorRemoveCommand = class {
58720
58750
  name = "vendor remove <name>";
58721
58751
  summary = "Take an installed charter away";
58722
- options = OPTIONS16;
58752
+ options = OPTIONS17;
58723
58753
  async run({ charterVendoringApp: charterVendoringApp2 }, { name }) {
58724
58754
  const folder = await charterVendoringApp2.remove(name ?? "");
58725
58755
  return {
@@ -58756,7 +58786,8 @@ var COMMANDS = [
58756
58786
  new VendorListCommand(),
58757
58787
  new PortalCommand(),
58758
58788
  new McpAuthCommand(),
58759
- new McpServeCommand()
58789
+ new McpServeCommand(),
58790
+ new SensorRunCommand()
58760
58791
  ];
58761
58792
 
58762
58793
  // src/driver/cli/Commander.ts
@@ -60077,11 +60108,11 @@ var WorkspaceSettings = class {
60077
60108
 
60078
60109
  // src/hexagon/service/settingsRepo.ts
60079
60110
  async function loadSettings(repo, fileReaders) {
60080
- const text = await fileReaders.readIfThere(settingsFileIn(repo));
60081
- if (text === void 0) return new WorkspaceSettings([]);
60111
+ const text2 = await fileReaders.readIfThere(settingsFileIn(repo));
60112
+ if (text2 === void 0) return new WorkspaceSettings([]);
60082
60113
  let written;
60083
60114
  try {
60084
- written = JSON.parse(text);
60115
+ written = JSON.parse(text2);
60085
60116
  } catch {
60086
60117
  throw new SettingsFault(
60087
60118
  `These are this repository's own settings and this is not JSON.`,
@@ -60137,10 +60168,10 @@ async function addTestSuite(repo, fileReaders, fileWriter2) {
60137
60168
  await fileWriter2.write(new URL(name, testFolderIn(repo)), DEFAULT_TEST_SUITE_BODY);
60138
60169
  return name;
60139
60170
  }
60140
- async function writeTestSuite(repo, fileReaders, fileWriter2, name, text) {
60171
+ async function writeTestSuite(repo, fileReaders, fileWriter2, name, text2) {
60141
60172
  await ensureTestSuiteNamed(repo, fileReaders, name);
60142
- testSuiteOf(text);
60143
- await fileWriter2.write(new URL(name, testFolderIn(repo)), text);
60173
+ testSuiteOf(text2);
60174
+ await fileWriter2.write(new URL(name, testFolderIn(repo)), text2);
60144
60175
  return name;
60145
60176
  }
60146
60177
  async function removeTestSuite(repo, fileReaders, fileWriter2, name) {
@@ -60387,22 +60418,24 @@ function isStamped(contents) {
60387
60418
 
60388
60419
  // src/hexagon/domain/models/output/CharterOutput.ts
60389
60420
  var CharterOutput = class {
60390
- constructor(catalogue, charterMd, compiledPrimitives, mcpOrigins, providerComponents) {
60421
+ constructor(catalogue, charterMd, compiledPrimitives, mcpOrigins, builtSensors, providerComponents) {
60391
60422
  this.catalogue = catalogue;
60392
60423
  this.charterMd = charterMd;
60393
60424
  this.compiledPrimitives = compiledPrimitives;
60394
60425
  this.mcpOrigins = mcpOrigins;
60426
+ this.builtSensors = builtSensors;
60395
60427
  this.providerComponents = providerComponents;
60396
60428
  }
60397
60429
  catalogue;
60398
60430
  charterMd;
60399
60431
  compiledPrimitives;
60400
60432
  mcpOrigins;
60433
+ builtSensors;
60401
60434
  providerComponents;
60402
60435
  /** Every file this output is put down as: what each of its parts says it is
60403
60436
  * put down as, together (FR-020, FR-021). */
60404
60437
  get projections() {
60405
- return [this.catalogue, this.mcpOrigins, this.charterMd, ...this.compiledPrimitives, ...this.providerComponents].flatMap(
60438
+ return [this.catalogue, this.mcpOrigins, this.builtSensors, this.charterMd, ...this.compiledPrimitives, ...this.providerComponents].flatMap(
60406
60439
  (outputPart) => outputPart.projections
60407
60440
  );
60408
60441
  }
@@ -60528,6 +60561,36 @@ function compiledPrimitiveOf(charter, primitive) {
60528
60561
  );
60529
60562
  }
60530
60563
 
60564
+ // src/hexagon/domain/models/output/common/BuiltSensor.ts
60565
+ function sensorRunCommandOf(signal) {
60566
+ return `cw sensor run ${signal}`;
60567
+ }
60568
+ var BuiltSensors = class {
60569
+ constructor(sensors) {
60570
+ this.sensors = sensors;
60571
+ }
60572
+ sensors;
60573
+ /** The file it is put down as, in the output folder: generated, and the
60574
+ * charter's alone. Indented, since it is committed and read in diffs when a
60575
+ * sensor's command changes. */
60576
+ get projections() {
60577
+ return [
60578
+ {
60579
+ file: `${OUT_DIRECTORY}/sensors.json`,
60580
+ contents: `${JSON.stringify({ sensors: this.sensors }, void 0, 2)}
60581
+ `,
60582
+ projectionPolicy: "replace",
60583
+ executable: false
60584
+ }
60585
+ ];
60586
+ }
60587
+ /** Every signal at least one sensor names, each once, in the order the
60588
+ * sensors name them. */
60589
+ get signals() {
60590
+ return [...new Set(this.sensors.map((builtSensor) => builtSensor.signal))];
60591
+ }
60592
+ };
60593
+
60531
60594
  // src/hexagon/domain/models/output/provider-component/ProviderComponent.ts
60532
60595
  var ProviderComponent = class {
60533
60596
  constructor(path, document, projectionPolicy) {
@@ -60672,7 +60735,7 @@ var ClaudeSettings = class _ClaudeSettings extends SettingBasedComponent {
60672
60735
  };
60673
60736
 
60674
60737
  // src/hexagon/domain/services/compile/claudeComponentFactory.ts
60675
- function claudeComponentsOf(charter, compiledPrimitiveByPrimitive, shortMcpIds) {
60738
+ function claudeComponentsOf(charter, compiledPrimitiveByPrimitive, shortMcpIds, builtSensors) {
60676
60739
  const isSettingComponent = (one) => one.kind === PosturePrimitive.kind || one.kind === SensorPrimitive.kind;
60677
60740
  const asSettings = charter.primitives.filter(isSettingComponent);
60678
60741
  const asDocuments = charter.primitives.filter((one) => !isSettingComponent(one));
@@ -60690,7 +60753,7 @@ function claudeComponentsOf(charter, compiledPrimitiveByPrimitive, shortMcpIds)
60690
60753
  // The section of `CLAUDE.md` that sends this host to the charter at all
60691
60754
  // (FR-051).
60692
60755
  ClaudeEntryFile.of(),
60693
- ...asSettings.length === 0 && toolsByMcpId.size === 0 ? [] : [ClaudeSettings.of(claudeSettingsOf(charter, compiledPrimitiveByPrimitive, asSettings))],
60756
+ ...asSettings.length === 0 && toolsByMcpId.size === 0 ? [] : [ClaudeSettings.of(claudeSettingsOf(charter, builtSensors, asSettings))],
60694
60757
  ClaudeMcpConfig.of(),
60695
60758
  ...asDocuments.flatMap(
60696
60759
  (one) => claudeDocumentComponentOf(
@@ -60702,30 +60765,19 @@ function claudeComponentsOf(charter, compiledPrimitiveByPrimitive, shortMcpIds)
60702
60765
  )
60703
60766
  ];
60704
60767
  }
60705
- function claudeSettingsOf(charter, compiledPrimitiveByPrimitive, ones) {
60706
- const allow = /* @__PURE__ */ new Set();
60707
- const deny = /* @__PURE__ */ new Set();
60708
- const hooks = {};
60709
- for (const one of ones) {
60710
- if (one.kind === PosturePrimitive.kind) {
60711
- const headers = one.headers;
60712
- for (const permission of headers.allow) allow.add(permission);
60713
- for (const permission of headers.deny) deny.add(permission);
60714
- }
60715
- if (one.kind === SensorPrimitive.kind) {
60716
- const { signal, run: run3 } = one.headers;
60717
- const command2 = run3.replace(REFERENCE, (reference, referencedId) => {
60718
- const scriptPrimitive = charter.primitiveById.get(referencedId);
60719
- const executionFile = scriptPrimitive && compiledPrimitiveByPrimitive.get(scriptPrimitive)?.projections.find((projection) => projection.executable)?.file;
60720
- return executionFile ?? reference;
60721
- });
60722
- if (isClaudeHookEvent(signal))
60723
- hooks[signal] = [...hooks[signal] ?? [], { hooks: [{ type: "command", command: command2 }] }];
60768
+ function claudeSettingsOf(charter, builtSensors, settingPrimitives) {
60769
+ const allowedPermissions = /* @__PURE__ */ new Set();
60770
+ const deniedPermissions = /* @__PURE__ */ new Set();
60771
+ for (const settingPrimitive of settingPrimitives) {
60772
+ if (settingPrimitive.kind === PosturePrimitive.kind) {
60773
+ for (const permission of settingPrimitive.headers.allow) allowedPermissions.add(permission);
60774
+ for (const permission of settingPrimitive.headers.deny) deniedPermissions.add(permission);
60724
60775
  }
60725
60776
  }
60777
+ const hookEvents = builtSensors.signals.filter(isClaudeHookEvent).sort();
60726
60778
  return {
60727
- ...allow.size === 0 && deny.size === 0 ? {} : { permissions: { allow: [...allow], deny: [...deny] } },
60728
- ...Object.keys(hooks).length === 0 ? {} : { hooks },
60779
+ ...allowedPermissions.size === 0 && deniedPermissions.size === 0 ? {} : { permissions: { allow: [...allowedPermissions], deny: [...deniedPermissions] } },
60780
+ ...hookEvents.length === 0 ? {} : { hooks: Object.fromEntries(hookEvents.map((hookEvent) => [hookEvent, [{ hooks: [{ type: "command", command: sensorRunCommandOf(hookEvent) }] }]])) },
60729
60781
  // A charter reaching an mcp origin has its tools' schemas deferred by the host
60730
60782
  // itself, the one server listing every tool (EVAL-FR-016).
60731
60783
  ...charter.primitives.some((primitive) => primitive instanceof McpPrimitive) && { env: CLAUDE_TOOL_SEARCH_ENV }
@@ -60805,6 +60857,19 @@ function mcpOriginsOf(charter, shortMcpIds, toolsByOriginKey = /* @__PURE__ */ n
60805
60857
  });
60806
60858
  }
60807
60859
 
60860
+ // src/hexagon/domain/services/compile/builtSensorsFactory.ts
60861
+ function builtSensorsOf(charter, compiledPrimitiveByPrimitive) {
60862
+ return [...charter.primitives].flatMap((primitive) => primitive.kind === SensorPrimitive.kind ? [primitive] : []).sort((one, another) => one.headers.id < another.headers.id ? -1 : 1).map(({ headers: { id, signal, run: run3 } }) => ({
60863
+ id,
60864
+ signal,
60865
+ command: run3.replace(REFERENCE, (reference, referencedId) => {
60866
+ const scriptPrimitive = charter.primitiveById.get(referencedId);
60867
+ const executionFile = scriptPrimitive && compiledPrimitiveByPrimitive.get(scriptPrimitive)?.projections.find((projection) => projection.executable)?.file;
60868
+ return executionFile ?? reference;
60869
+ })
60870
+ }));
60871
+ }
60872
+
60808
60873
  // src/hexagon/domain/services/compile/compileService.ts
60809
60874
  function compile2(charter, agents, toolsByOriginKey = /* @__PURE__ */ new Map()) {
60810
60875
  const shortMcpIds = shortenStringsOf(
@@ -60813,6 +60878,7 @@ function compile2(charter, agents, toolsByOriginKey = /* @__PURE__ */ new Map())
60813
60878
  const compiledPrimitiveByPrimitive = new Map(
60814
60879
  [...charter.primitives].sort((one, another) => one.headers.id < another.headers.id ? -1 : one.headers.id > another.headers.id ? 1 : 0).map((primitive) => [primitive, compiledPrimitiveOf(charter, primitive)])
60815
60880
  );
60881
+ const builtSensors = new BuiltSensors(builtSensorsOf(charter, compiledPrimitiveByPrimitive));
60816
60882
  return new CharterOutput(
60817
60883
  // What an agent opens from the catalogue is the primitive as it compiled,
60818
60884
  // not the file its author wrote: the whole body in one place, under the
@@ -60822,13 +60888,14 @@ function compile2(charter, agents, toolsByOriginKey = /* @__PURE__ */ new Map())
60822
60888
  charterMdOf(PRIMITIVE_CLASSES),
60823
60889
  [...compiledPrimitiveByPrimitive.values()],
60824
60890
  new McpOrigins(mcpOriginsOf(charter, shortMcpIds, toolsByOriginKey)),
60825
- agents.flatMap((agent) => providerComponentsOf(agent, charter, compiledPrimitiveByPrimitive, shortMcpIds))
60891
+ builtSensors,
60892
+ agents.flatMap((agent) => providerComponentsOf(agent, charter, compiledPrimitiveByPrimitive, shortMcpIds, builtSensors))
60826
60893
  );
60827
60894
  }
60828
- function providerComponentsOf(agent, charter, compiledPrimitiveByPrimitive, shortMcpIds) {
60895
+ function providerComponentsOf(agent, charter, compiledPrimitiveByPrimitive, shortMcpIds, builtSensors) {
60829
60896
  switch (agent) {
60830
60897
  case "claude":
60831
- return claudeComponentsOf(charter, compiledPrimitiveByPrimitive, shortMcpIds);
60898
+ return claudeComponentsOf(charter, compiledPrimitiveByPrimitive, shortMcpIds, builtSensors);
60832
60899
  }
60833
60900
  }
60834
60901
 
@@ -61099,7 +61166,7 @@ function tokenFactorOf(agent) {
61099
61166
  function estimatedMainContextOf(charter, agent, tokenCounter2) {
61100
61167
  return new MainContext(
61101
61168
  agent,
61102
- mainContextTextsOf(charter, agent).map(({ text, ...mainContextText }) => ({ ...mainContextText, tokens: Math.round(tokenCounter2.countTokens(text) * tokenFactorOf(agent)) })),
61169
+ mainContextTextsOf(charter, agent).map(({ text: text2, ...mainContextText }) => ({ ...mainContextText, tokens: Math.round(tokenCounter2.countTokens(text2) * tokenFactorOf(agent)) })),
61103
61170
  false
61104
61171
  );
61105
61172
  }
@@ -61112,7 +61179,7 @@ async function exactMainContextOf(charter, agent, agentCli) {
61112
61179
  const countTokensFromAnswer = ({ usage: { inputTokens, cacheCreationInputTokens, cacheReadInputTokens } }) => inputTokens + cacheCreationInputTokens + cacheReadInputTokens;
61113
61180
  const ownTokens = countTokensFromAnswer(await agentCli.ask("."));
61114
61181
  const mainContextTexts = mainContextTextsOf(charter, agent);
61115
- const sentTokenCounts = await Promise.all(mainContextTexts.map(async ({ text }) => countTokensFromAnswer(await agentCli.ask(text))));
61182
+ const sentTokenCounts = await Promise.all(mainContextTexts.map(async ({ text: text2 }) => countTokensFromAnswer(await agentCli.ask(text2))));
61116
61183
  return new MainContext(
61117
61184
  agent,
61118
61185
  mainContextTexts.map(({ text: _text, ...mainContextText }, index) => ({ ...mainContextText, tokens: Math.max(0, sentTokenCounts[index] - ownTokens) })),
@@ -61630,27 +61697,27 @@ var TestAuthoring = class {
61630
61697
  async addSuite() {
61631
61698
  return addTestSuite(this.#repoPath, this.#fileReader, this.#fileWriter);
61632
61699
  }
61633
- async writeSuite(name, text) {
61634
- return writeTestSuite(this.#repoPath, this.#fileReader, this.#fileWriter, name, text);
61700
+ async writeSuite(name, text2) {
61701
+ return writeTestSuite(this.#repoPath, this.#fileReader, this.#fileWriter, name, text2);
61635
61702
  }
61636
61703
  async removeSuite(name) {
61637
61704
  return removeTestSuite(this.#repoPath, this.#fileReader, this.#fileWriter, name);
61638
61705
  }
61639
61706
  };
61640
61707
 
61641
- // src/hexagon/port/zdriven/DrivenFault.ts
61642
- var DrivenFault = class extends DomainFault {
61708
+ // src/hexagon/port/zdriven/AdapterFault.ts
61709
+ var AdapterFault = class extends DomainFault {
61643
61710
  };
61644
61711
 
61645
61712
  // src/hexagon/port/zdriven/ForCallingMcpServers.ts
61646
- var UnauthorizedMcpFault = class extends DrivenFault {
61713
+ var UnauthorizedMcpFault = class extends AdapterFault {
61647
61714
  };
61648
61715
 
61649
61716
  // src/hexagon/application/McpConnecting.ts
61650
61717
  var CONNECT_TIMEOUT_MS = 1e4;
61651
- var errorAnswerOf = (text) => ({
61718
+ var errorAnswerOf = (text2) => ({
61652
61719
  type: "ToolAnswer",
61653
- data: { content: [{ type: "text", text }], isError: true }
61720
+ data: { content: [{ type: "text", text: text2 }], isError: true }
61654
61721
  });
61655
61722
  var McpConnecting = class {
61656
61723
  #repoPath;
@@ -61947,10 +62014,10 @@ var EvalSuiteSchema = external_exports.strictObject({
61947
62014
  var SAMPLE2 = JSON.stringify({
61948
62015
  cases: [{ prompt: "plan this feature: export a report", expect: { invoke: "sdd-plan", follow: "plain-names", maxTokens: 2e5 } }]
61949
62016
  });
61950
- function evalSuiteOf(text) {
62017
+ function evalSuiteOf(text2) {
61951
62018
  let evalSuiteJson;
61952
62019
  try {
61953
- evalSuiteJson = JSON.parse(text);
62020
+ evalSuiteJson = JSON.parse(text2);
61954
62021
  } catch {
61955
62022
  throw new EvalSuiteFault(`This file is not JSON, so nothing can read the cases it was meant to hold.`, `Write it as ${SAMPLE2}`);
61956
62023
  }
@@ -62150,6 +62217,92 @@ var CharterEvaluating = class {
62150
62217
  }
62151
62218
  };
62152
62219
 
62220
+ // src/hexagon/domain/models/sensor/SensorAnswer.ts
62221
+ var CONTEXT_SIGNALS = ["UserPromptSubmit", "SessionStart"];
62222
+ var PERMISSION_DECISIONS = ["deny", "ask", "allow"];
62223
+ function signalAnswerOf(signal, sensorAnswers) {
62224
+ const blockingAnswers = sensorAnswers.filter((sensorAnswer) => sensorAnswer.exitCode === 2);
62225
+ const failedAnswers = sensorAnswers.filter((sensorAnswer) => sensorAnswer.exitCode !== 0);
62226
+ const exitCode = blockingAnswers.length > 0 ? 2 : failedAnswers[0]?.exitCode ?? 0;
62227
+ const stderr = (blockingAnswers.length > 0 ? blockingAnswers : failedAnswers).map((sensorAnswer) => sensorAnswer.stderr).join("");
62228
+ const answerTexts = sensorAnswers.map((sensorAnswer) => sensorAnswer.stdout.trim()).filter((answerText) => answerText !== "");
62229
+ const isPlainObject3 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
62230
+ const structuredAnswers = answerTexts.map((answerText) => {
62231
+ try {
62232
+ const answerJSON = JSON.parse(answerText);
62233
+ return isPlainObject3(answerJSON) ? answerJSON : void 0;
62234
+ } catch {
62235
+ return void 0;
62236
+ }
62237
+ });
62238
+ if (structuredAnswers.every((structuredAnswer) => structuredAnswer === void 0))
62239
+ return { exitCode, stdout: answerTexts.map((answerText) => `${answerText}
62240
+ `).join(""), stderr };
62241
+ const plainTexts = answerTexts.filter((_answerText, index) => structuredAnswers[index] === void 0);
62242
+ const answerJSONs = structuredAnswers.filter((structuredAnswer) => structuredAnswer !== void 0);
62243
+ const hookSpecificOutputs = answerJSONs.map((answerJSON) => answerJSON["hookSpecificOutput"]).filter(isPlainObject3);
62244
+ const joinedTextOf = (values) => values.filter((value) => typeof value === "string" && value !== "").join("\n");
62245
+ const combinedAnswer = Object.assign({}, ...[...answerJSONs].reverse());
62246
+ const combinedHookSpecificOutput = Object.assign({}, ...[...hookSpecificOutputs].reverse());
62247
+ const stoppingAnswers = answerJSONs.filter((answerJSON) => answerJSON["continue"] === false);
62248
+ if (stoppingAnswers.length > 0) {
62249
+ combinedAnswer["continue"] = false;
62250
+ combinedAnswer["stopReason"] = joinedTextOf(stoppingAnswers.map((answerJSON) => answerJSON["stopReason"]));
62251
+ }
62252
+ if ("suppressOutput" in combinedAnswer) combinedAnswer["suppressOutput"] = answerJSONs.every((answerJSON) => answerJSON["suppressOutput"] === true);
62253
+ const blockingJSONs = answerJSONs.filter((answerJSON) => answerJSON["decision"] === "block");
62254
+ if (blockingJSONs.length > 0) {
62255
+ combinedAnswer["decision"] = "block";
62256
+ combinedAnswer["reason"] = joinedTextOf(blockingJSONs.map((answerJSON) => answerJSON["reason"]));
62257
+ }
62258
+ const isContextSignal = CONTEXT_SIGNALS.includes(signal);
62259
+ const systemMessage = joinedTextOf([...answerJSONs.map((answerJSON) => answerJSON["systemMessage"]), ...isContextSignal ? [] : plainTexts]);
62260
+ if (systemMessage !== "") combinedAnswer["systemMessage"] = systemMessage;
62261
+ const permissionDecision = PERMISSION_DECISIONS.find((rankedDecision) => hookSpecificOutputs.some((hookSpecificOutput) => hookSpecificOutput["permissionDecision"] === rankedDecision));
62262
+ if (permissionDecision !== void 0) {
62263
+ combinedHookSpecificOutput["permissionDecision"] = permissionDecision;
62264
+ combinedHookSpecificOutput["permissionDecisionReason"] = joinedTextOf(
62265
+ hookSpecificOutputs.filter((hookSpecificOutput) => hookSpecificOutput["permissionDecision"] === permissionDecision).map((hookSpecificOutput) => hookSpecificOutput["permissionDecisionReason"])
62266
+ );
62267
+ }
62268
+ const additionalContext = joinedTextOf([...hookSpecificOutputs.map((hookSpecificOutput) => hookSpecificOutput["additionalContext"]), ...isContextSignal ? plainTexts : []]);
62269
+ if (additionalContext !== "") combinedHookSpecificOutput["additionalContext"] = additionalContext;
62270
+ if (Object.keys(combinedHookSpecificOutput).length > 0) combinedAnswer["hookSpecificOutput"] = { ...combinedHookSpecificOutput, hookEventName: signal };
62271
+ return { exitCode, stdout: `${JSON.stringify(combinedAnswer)}
62272
+ `, stderr };
62273
+ }
62274
+
62275
+ // src/hexagon/service/sensorsRepo.ts
62276
+ async function loadBuiltSensors(repo, fileReader2) {
62277
+ const contents = await fileReader2.readIfThere(new URL("sensors.json", outFolderIn(repo)));
62278
+ try {
62279
+ const sensorsJson = JSON.parse(contents ?? "{}");
62280
+ const sensors = sensorsJson.sensors;
62281
+ if (Array.isArray(sensors)) return new BuiltSensors(sensors);
62282
+ } catch {
62283
+ }
62284
+ return new BuiltSensors([]);
62285
+ }
62286
+
62287
+ // src/hexagon/application/SensorRunning.ts
62288
+ var SensorRunning = class {
62289
+ #repoPath;
62290
+ #fileReader;
62291
+ #shell;
62292
+ constructor(repoPath2, fileReader2, shell2) {
62293
+ this.#repoPath = repoPath2;
62294
+ this.#fileReader = fileReader2;
62295
+ this.#shell = shell2;
62296
+ }
62297
+ async runSensors(signal, stdin) {
62298
+ const builtSensors = await loadBuiltSensors(this.#repoPath, this.#fileReader);
62299
+ const sensorAnswers = await Promise.all(
62300
+ builtSensors.sensors.filter((builtSensor) => builtSensor.signal === signal).map((builtSensor) => this.#shell.runShellCommand(builtSensor.command, this.#repoPath, stdin))
62301
+ );
62302
+ return sensorRunOutcomeDTO(signalAnswerOf(signal, sensorAnswers));
62303
+ }
62304
+ };
62305
+
62153
62306
  // src/zdriven/FileReaders.ts
62154
62307
  import { readdir, readFile, stat } from "fs/promises";
62155
62308
  var FileReaders = class {
@@ -62305,7 +62458,7 @@ var Git = class {
62305
62458
  try {
62306
62459
  await run("git", ["fetch", "--quiet", "--no-tags", "--", source, ref], { cwd });
62307
62460
  } catch (raised) {
62308
- throw new DrivenFault(
62461
+ throw new AdapterFault(
62309
62462
  `${raised}`,
62310
62463
  version2 === void 0 ? "Check the address, and that you can reach it from here." : `Check the address, and that "${version2}" is a tag or branch it has.`
62311
62464
  );
@@ -62318,9 +62471,9 @@ var Git = class {
62318
62471
  const atVersion = version2 === void 0 ? "" : ` at ${version2}`;
62319
62472
  const [requiredPath = ""] = includePaths;
62320
62473
  if (await objectTypeAt(requiredPath) === void 0)
62321
- throw new DrivenFault(`${source} has no "${requiredPath}"${atVersion}.`, `Check that the source holds "${requiredPath}" at the version asked for.`);
62474
+ throw new AdapterFault(`${source} has no "${requiredPath}"${atVersion}.`, `Check that the source holds "${requiredPath}" at the version asked for.`);
62322
62475
  if (refusedIfSourceHolds !== void 0 && await objectTypeAt(refusedIfSourceHolds) === "tree")
62323
- throw new DrivenFault(
62476
+ throw new AdapterFault(
62324
62477
  `${source} holds "${refusedIfSourceHolds}"${atVersion}, which this copy refuses.`,
62325
62478
  `Remove "${refusedIfSourceHolds}" from the source, or copy a version without it.`
62326
62479
  );
@@ -62345,7 +62498,7 @@ var Git = class {
62345
62498
  return intoSubFolder;
62346
62499
  } catch (raised) {
62347
62500
  await run("git", ["restore", "--source=HEAD", "--worktree", "--", intoSubFolder], { cwd }).catch(() => void 0);
62348
- throw new DrivenFault(`${raised}`, `Check that "${intoSubFolder}" can be written, and run this again.`);
62501
+ throw new AdapterFault(`${raised}`, `Check that "${intoSubFolder}" can be written, and run this again.`);
62349
62502
  } finally {
62350
62503
  await rm2(vendorIndexPath, { force: true });
62351
62504
  }
@@ -62359,7 +62512,7 @@ var Git = class {
62359
62512
  await run("git", ["rm", "-r", "--quiet", "--", subFolder], { cwd });
62360
62513
  await run("git", ["commit", "-qm", `Remove ${subFolder}`], { cwd });
62361
62514
  } catch (raised) {
62362
- throw new DrivenFault(`${raised}`, `Check that "${subFolder}" is a folder this repository holds.`);
62515
+ throw new AdapterFault(`${raised}`, `Check that "${subFolder}" is a folder this repository holds.`);
62363
62516
  }
62364
62517
  }
62365
62518
  /** `git worktree add --detach` at `HEAD`, forced over a record of one
@@ -62368,7 +62521,7 @@ var Git = class {
62368
62521
  try {
62369
62522
  await run("git", ["worktree", "add", "--quiet", "--detach", "--force", fileURLToPath3(worktreeFolder), "HEAD"], { cwd: fileURLToPath3(repo) });
62370
62523
  } catch (raised) {
62371
- throw new DrivenFault(`${raised}`, "Commit what is to be evaluated first: a worktree holds the last commit.");
62524
+ throw new AdapterFault(`${raised}`, "Commit what is to be evaluated first: a worktree holds the last commit.");
62372
62525
  }
62373
62526
  }
62374
62527
  /** `git worktree remove --force`, then the folder removed whatever git
@@ -62417,7 +62570,7 @@ var OsSecrets = class {
62417
62570
  async writeSecret(key, secret) {
62418
62571
  this.refuseUnsupportedPlatform();
62419
62572
  if (this.platform === "darwin" && /["\\\n]/.test(key)) {
62420
- throw new DrivenFault(`The key "${key}" cannot be kept in the keychain.`, "Name the mcp origin by an address without quotes, backslashes or line breaks.");
62573
+ throw new AdapterFault(`The key "${key}" cannot be kept in the keychain.`, "Name the mcp origin by an address without quotes, backslashes or line breaks.");
62421
62574
  }
62422
62575
  const commandOutputOfWrite = this.platform === "darwin" ? await commandOutput(
62423
62576
  "security",
@@ -62442,7 +62595,7 @@ var OsSecrets = class {
62442
62595
  * before a command runs. */
62443
62596
  refuseUnsupportedPlatform() {
62444
62597
  if (this.platform !== "darwin" && this.platform !== "linux") {
62445
- throw new DrivenFault(
62598
+ throw new AdapterFault(
62446
62599
  `Keeping a secret is not supported on "${this.platform}".`,
62447
62600
  "Sign in from macOS or Linux, whose credential stores cw uses."
62448
62601
  );
@@ -62450,7 +62603,7 @@ var OsSecrets = class {
62450
62603
  }
62451
62604
  throwFault(operation, key, stderr = "") {
62452
62605
  const storeName = this.platform === "darwin" ? "The keychain" : "The secret service";
62453
- throw new DrivenFault(
62606
+ throw new AdapterFault(
62454
62607
  `${storeName} refused to ${operation} the secret for "${key}".${stderr.trim() === "" ? "" : ` It said: ${stderr.trim()}`}`,
62455
62608
  this.platform === "darwin" ? "Check that the login keychain is unlocked." : "Check that secret-tool is installed and a secret service is running."
62456
62609
  );
@@ -63379,7 +63532,7 @@ var OAuth = class {
63379
63532
  let callbackTimeout;
63380
63533
  const authorizationCode = new Promise((resolve5, reject) => {
63381
63534
  callbackTimeout = setTimeout(
63382
- () => reject(new DrivenFault(`Nobody came back from signing in to ${endpoint} in time.`, 'Run "cw mcp auth" again, and open the address it prints.')),
63535
+ () => reject(new AdapterFault(`Nobody came back from signing in to ${endpoint} in time.`, 'Run "cw mcp auth" again, and open the address it prints.')),
63383
63536
  this.#callbackTimeoutMs
63384
63537
  );
63385
63538
  callbackServer.on("request", (request, response) => {
@@ -63390,7 +63543,7 @@ var OAuth = class {
63390
63543
  response.writeHead(200, { "content-type": "text/plain; charset=utf-8" }).end(signedIn ? "Signed in. Go back to the terminal.\n" : "Not signed in. Go back to the terminal.\n");
63391
63544
  if (signedIn) return resolve5(callbackCode);
63392
63545
  const callbackError = callbackUrl.searchParams.get("error");
63393
- reject(new DrivenFault(`Signing in to ${endpoint} came back without an authorization${callbackError ? `: ${callbackError}` : ""}.`, 'Run "cw mcp auth" again.'));
63546
+ reject(new AdapterFault(`Signing in to ${endpoint} came back without an authorization${callbackError ? `: ${callbackError}` : ""}.`, 'Run "cw mcp auth" again.'));
63394
63547
  });
63395
63548
  });
63396
63549
  authorizationCode.catch(() => void 0);
@@ -63401,8 +63554,8 @@ var OAuth = class {
63401
63554
  await auth(provider, { serverUrl: endpoint, authorizationCode: await authorizationCode });
63402
63555
  return oauthGrantOf(endpoint, oauthSession);
63403
63556
  } catch (raised) {
63404
- if (raised instanceof DrivenFault) throw raised;
63405
- throw new DrivenFault(
63557
+ if (raised instanceof AdapterFault) throw raised;
63558
+ throw new AdapterFault(
63406
63559
  `Signing in to ${endpoint} failed: ${raised instanceof Error ? raised.message : String(raised)}`,
63407
63560
  'Check the address is reachable and offers an OAuth sign-in, then run "cw mcp auth" again.'
63408
63561
  );
@@ -63428,7 +63581,7 @@ var OAuth = class {
63428
63581
  if (await auth(provider, { serverUrl: endpoint }) === "REDIRECT") return void 0;
63429
63582
  } catch (raised) {
63430
63583
  if (raised instanceof OAuthError) return void 0;
63431
- throw new DrivenFault(
63584
+ throw new AdapterFault(
63432
63585
  `Renewing the sign-in to ${endpoint} failed: ${raised instanceof Error ? raised.message : String(raised)}`,
63433
63586
  "Check the address is reachable, then try again."
63434
63587
  );
@@ -63473,7 +63626,7 @@ var OAuth = class {
63473
63626
  };
63474
63627
  function oauthGrantOf(endpoint, { clientInformation, tokens }) {
63475
63628
  if (clientInformation === void 0 || tokens === void 0)
63476
- throw new DrivenFault(`Signing in to ${endpoint} ended without a token.`, 'Run "cw mcp auth" again.');
63629
+ throw new AdapterFault(`Signing in to ${endpoint} ended without a token.`, 'Run "cw mcp auth" again.');
63477
63630
  return {
63478
63631
  accessToken: tokens.access_token,
63479
63632
  ...tokens.refresh_token !== void 0 && { refreshToken: tokens.refresh_token },
@@ -64827,7 +64980,7 @@ var StreamableHTTPClientTransport = class {
64827
64980
  this._sessionId = sessionId;
64828
64981
  }
64829
64982
  if (!response.ok) {
64830
- const text = await response.text().catch(() => null);
64983
+ const text2 = await response.text().catch(() => null);
64831
64984
  if (response.status === 401 && this._authProvider) {
64832
64985
  if (this._hasCompletedAuthFlow) {
64833
64986
  throw new StreamableHTTPError(401, "Server returned 401 after successful authentication");
@@ -64873,7 +65026,7 @@ var StreamableHTTPClientTransport = class {
64873
65026
  return this.send(message);
64874
65027
  }
64875
65028
  }
64876
- throw new StreamableHTTPError(response.status, `Error POSTing to endpoint: ${text}`);
65029
+ throw new StreamableHTTPError(response.status, `Error POSTing to endpoint: ${text2}`);
64877
65030
  }
64878
65031
  this._hasCompletedAuthFlow = false;
64879
65032
  this._lastUpscopingHeader = void 0;
@@ -64993,7 +65146,7 @@ var McpClients = class {
64993
65146
  client.connect(transport).then(() => client.listTools()),
64994
65147
  new Promise((_resolve, reject) => {
64995
65148
  connectTimeout = setTimeout(
64996
- () => reject(new DrivenFault(`${address} did not answer within ${timeoutMs / 1e3} seconds.`, "Check the mcp origin is up, then start the server again.")),
65149
+ () => reject(new AdapterFault(`${address} did not answer within ${timeoutMs / 1e3} seconds.`, "Check the mcp origin is up, then start the server again.")),
64997
65150
  timeoutMs
64998
65151
  );
64999
65152
  })
@@ -65019,10 +65172,10 @@ var McpClients = class {
65019
65172
  }
65020
65173
  };
65021
65174
  function faultOf(raised, failed, fix) {
65022
- if (raised instanceof DrivenFault) return raised;
65175
+ if (raised instanceof AdapterFault) return raised;
65023
65176
  if (raised instanceof StreamableHTTPError && raised.code === 401)
65024
65177
  return new UnauthorizedMcpFault(`${failed}: the mcp origin refused your credential.`, 'Run "cw mcp auth" at a terminal to sign in there again.');
65025
- return new DrivenFault(`${failed}: ${raised instanceof Error ? raised.message : String(raised)}`, fix);
65178
+ return new AdapterFault(`${failed}: ${raised instanceof Error ? raised.message : String(raised)}`, fix);
65026
65179
  }
65027
65180
 
65028
65181
  // node_modules/.pnpm/js-tiktoken@1.0.21/node_modules/js-tiktoken/dist/chunk-VL2OQCWN.js
@@ -65096,12 +65249,12 @@ var _Tiktoken = class {
65096
65249
  this.textMap.set(rank, bytes);
65097
65250
  }
65098
65251
  this.specialTokens = { ...ranks.special_tokens, ...extendedSpecialTokens };
65099
- this.inverseSpecialTokens = Object.entries(this.specialTokens).reduce((memo2, [text, rank]) => {
65100
- memo2[rank] = this.textEncoder.encode(text);
65252
+ this.inverseSpecialTokens = Object.entries(this.specialTokens).reduce((memo2, [text2, rank]) => {
65253
+ memo2[rank] = this.textEncoder.encode(text2);
65101
65254
  return memo2;
65102
65255
  }, {});
65103
65256
  }
65104
- encode(text, allowedSpecial = [], disallowedSpecial = "all") {
65257
+ encode(text2, allowedSpecial = [], disallowedSpecial = "all") {
65105
65258
  const regexes = new RegExp(this.patStr, "ug");
65106
65259
  const specialRegex = _Tiktoken.specialTokenRegex(
65107
65260
  Object.keys(this.specialTokens)
@@ -65119,7 +65272,7 @@ var _Tiktoken = class {
65119
65272
  const disallowedSpecialRegex = _Tiktoken.specialTokenRegex([
65120
65273
  ...disallowedSpecialSet
65121
65274
  ]);
65122
- const specialMatch = text.match(disallowedSpecialRegex);
65275
+ const specialMatch = text2.match(disallowedSpecialRegex);
65123
65276
  if (specialMatch != null) {
65124
65277
  throw new Error(
65125
65278
  `The text contains a special token that is not allowed: ${specialMatch[0]}`
@@ -65132,13 +65285,13 @@ var _Tiktoken = class {
65132
65285
  let startFind = start;
65133
65286
  while (true) {
65134
65287
  specialRegex.lastIndex = startFind;
65135
- nextSpecial = specialRegex.exec(text);
65288
+ nextSpecial = specialRegex.exec(text2);
65136
65289
  if (nextSpecial == null || allowedSpecialSet.has(nextSpecial[0]))
65137
65290
  break;
65138
65291
  startFind = nextSpecial.index + 1;
65139
65292
  }
65140
- const end = nextSpecial?.index ?? text.length;
65141
- for (const match2 of text.substring(start, end).matchAll(regexes)) {
65293
+ const end = nextSpecial?.index ?? text2.length;
65294
+ for (const match2 of text2.substring(start, end).matchAll(regexes)) {
65142
65295
  const piece = this.textEncoder.encode(match2[0]);
65143
65296
  const token2 = this.rankMap.get(piece.join(","));
65144
65297
  if (token2 != null) {
@@ -65186,9 +65339,9 @@ var o200k_base_default = { "pat_str": "[^\\r\\n\\p{L}\\p{N}]?[\\p{Lu}\\p{Lt}\\p{
65186
65339
  // src/zdriven/Tiktoken.ts
65187
65340
  var Tiktoken2 = class {
65188
65341
  #encoding;
65189
- countTokens(text) {
65342
+ countTokens(text2) {
65190
65343
  this.#encoding ??= new Tiktoken(o200k_base_default);
65191
- return this.#encoding.encode(text).length;
65344
+ return this.#encoding.encode(text2).length;
65192
65345
  }
65193
65346
  };
65194
65347
 
@@ -65245,12 +65398,12 @@ var ClaudeCli = class {
65245
65398
  claudeProcess.on("error", reject);
65246
65399
  claudeProcess.on(
65247
65400
  "close",
65248
- (code) => code === 0 ? resolve5(stdout) : reject(new DrivenFault(`"claude -p" stopped with status ${code}: ${stderr.trim()}`, 'Check that "claude" runs and is signed in here.'))
65401
+ (code) => code === 0 ? resolve5(stdout) : reject(new AdapterFault(`"claude -p" stopped with status ${code}: ${stderr.trim()}`, 'Check that "claude" runs and is signed in here.'))
65249
65402
  );
65250
65403
  claudeProcess.stdin.end(prompt);
65251
65404
  });
65252
65405
  const { is_error: isError, result: resultText } = JSON.parse(printedJson);
65253
- if (isError === true) throw new DrivenFault(`"claude -p" answered with an error: ${resultText ?? ""}`.trim(), 'Check that "claude" runs and is signed in here.');
65406
+ if (isError === true) throw new AdapterFault(`"claude -p" answered with an error: ${resultText ?? ""}`.trim(), 'Check that "claude" runs and is signed in here.');
65254
65407
  return printedJson;
65255
65408
  } finally {
65256
65409
  if (emptyFolder !== void 0) await rm3(emptyFolder, { recursive: true, force: true });
@@ -65297,7 +65450,7 @@ var Promptfoo = class {
65297
65450
  { cwd: this.installFolderPath, maxBuffer: 64 * 1024 * 1024 }
65298
65451
  );
65299
65452
  } catch (raised) {
65300
- throw new DrivenFault(`Installing promptfoo failed: ${raised}`, `Check that npm can reach the registry, then run "cw eval" again.`);
65453
+ throw new AdapterFault(`Installing promptfoo failed: ${raised}`, `Check that npm can reach the registry, then run "cw eval" again.`);
65301
65454
  }
65302
65455
  }
65303
65456
  async evaluate({ description, prompt, workingFolder, assertions }) {
@@ -65353,13 +65506,13 @@ var Promptfoo = class {
65353
65506
  });
65354
65507
  } catch (raised) {
65355
65508
  if (raised.code !== PROMPTFOO_FAILED_TEST_EXIT_CODE)
65356
- throw new DrivenFault(`"promptfoo eval" stopped with an error: ${raised.stderr?.trim() || raised}`, 'Check that "claude" runs and is signed in here.');
65509
+ throw new AdapterFault(`"promptfoo eval" stopped with an error: ${raised.stderr?.trim() || raised}`, 'Check that "claude" runs and is signed in here.');
65357
65510
  }
65358
65511
  const {
65359
65512
  results: { results: testResults }
65360
65513
  } = JSON.parse(await readFile2(outputFilePath, "utf8"));
65361
65514
  const [testResult] = testResults;
65362
- if (testResult === void 0) throw new DrivenFault('"promptfoo eval" wrote no result.', 'Run "cw eval" again.');
65515
+ if (testResult === void 0) throw new AdapterFault('"promptfoo eval" wrote no result.', 'Run "cw eval" again.');
65363
65516
  return {
65364
65517
  success: testResult.success,
65365
65518
  totalTokens: testResult.response?.tokenUsage?.total ?? 0,
@@ -65378,11 +65531,11 @@ var Promptfoo = class {
65378
65531
 
65379
65532
  // src/zdriven/ConsoleReporter.ts
65380
65533
  var ConsoleReporter = class {
65381
- report(text) {
65382
- process.stdout.write(text);
65534
+ report(text2) {
65535
+ process.stdout.write(text2);
65383
65536
  }
65384
- problem(text) {
65385
- process.stderr.write(text);
65537
+ problem(text2) {
65538
+ process.stderr.write(text2);
65386
65539
  }
65387
65540
  };
65388
65541
 
@@ -65393,6 +65546,29 @@ var SystemClock = class {
65393
65546
  }
65394
65547
  };
65395
65548
 
65549
+ // src/zdriven/Shell.ts
65550
+ import { spawn as spawn5 } from "child_process";
65551
+ import { fileURLToPath as fileURLToPath5 } from "url";
65552
+ var Shell = class {
65553
+ runShellCommand(command2, workingFolder, stdin) {
65554
+ return new Promise((resolve5) => {
65555
+ const childProcess = spawn5(command2, { shell: true, cwd: fileURLToPath5(workingFolder), stdio: "pipe" });
65556
+ const stdoutChunks = [];
65557
+ const stderrChunks = [];
65558
+ childProcess.stdout.on("data", (chunk) => stdoutChunks.push(chunk));
65559
+ childProcess.stderr.on("data", (chunk) => stderrChunks.push(chunk));
65560
+ childProcess.on("error", (raised) => resolve5({ exitCode: 1, stdout: "", stderr: `${raised.message}
65561
+ ` }));
65562
+ childProcess.on(
65563
+ "close",
65564
+ (exitCode) => resolve5({ exitCode: exitCode ?? 1, stdout: Buffer.concat(stdoutChunks).toString(), stderr: Buffer.concat(stderrChunks).toString() })
65565
+ );
65566
+ childProcess.stdin.on("error", () => void 0);
65567
+ childProcess.stdin.end(stdin);
65568
+ });
65569
+ }
65570
+ };
65571
+
65396
65572
  // main.ts
65397
65573
  var fileReader = new FileReaders();
65398
65574
  var yamlParser = new YamlParser();
@@ -65403,6 +65579,7 @@ var authorizing = new OAuth();
65403
65579
  var mcpServers = new McpClients();
65404
65580
  var tokenCounter = new Tiktoken2();
65405
65581
  var clock = new SystemClock();
65582
+ var shell = new Shell();
65406
65583
  var agentCliByProvider = { claude: new ClaudeCli() };
65407
65584
  var repoPath = pathToFileURL2(`${process.cwd()}/`);
65408
65585
  var charterAuthoringApp = new CharterAuthoring(
@@ -65425,6 +65602,7 @@ var sessionReviewingApp = new SessionReviewing(repoPath, homePath, fileReader, c
65425
65602
  var promptfooRunner = new Promptfoo(join6(homedir(), ".cherry-works"));
65426
65603
  var progressReporter = new ConsoleReporter();
65427
65604
  var charterEvaluatingApp = new CharterEvaluating(repoPath, fileReader, yamlParser, fileWriter, vcs, agentCliByProvider, promptfooRunner, progressReporter);
65605
+ var sensorRunningApp = new SensorRunning(repoPath, fileReader, shell);
65428
65606
  var cli = new Commander({
65429
65607
  cwd: process.cwd(),
65430
65608
  version: package_default.version,
@@ -65433,7 +65611,8 @@ var cli = new Commander({
65433
65611
  testAuthoringApp,
65434
65612
  mcpConnectingApp,
65435
65613
  sessionReviewingApp,
65436
- charterEvaluatingApp
65614
+ charterEvaluatingApp,
65615
+ sensorRunningApp
65437
65616
  });
65438
65617
  process.exitCode = await cli.run(process.argv.slice(2));
65439
65618
  /*! Bundled license information: