@garygentry/system1 0.2.0 → 0.3.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.
@@ -6,7 +6,7 @@ import {
6
6
  VERSION,
7
7
  emit,
8
8
  extractFormat
9
- } from "./chunk-PGNYF7TH.mjs";
9
+ } from "./chunk-NUIZJRI6.mjs";
10
10
 
11
11
  // src/bin.ts
12
12
  import { readFileSync as readFileSync2 } from "node:fs";
@@ -50,7 +50,8 @@ Commands:
50
50
  usage Measured spend from the ledger (--session, --since)
51
51
  config Show resolved config; \`config egress allow|deny|status\` for consent
52
52
  spec list | show <name> | validate [name|path] | check <name> [--live]
53
- schema Print the JSON Schema of a tool's input (ask, many, usage, spec-check)
53
+ schema Print the JSON Schema of a tool's input (ask, many, usage, spec-check, route)
54
+ route Does a prompt call for the ask skill? (--text|--stdin|--hook; local, sends nothing)
54
55
  ping Check the endpoint is reachable (no key, no spend)
55
56
  doctor Check decide works from this shell; prints the fix for each problem
56
57
  version Print the version
@@ -91,21 +92,23 @@ async function main(argv, io) {
91
92
  }
92
93
  switch (command) {
93
94
  case "ask":
94
- return (await import("./decide-UOND3JAL.mjs")).runAskCommand(rest, io, format);
95
+ return (await import("./decide-XVVRKQ3V.mjs")).runAskCommand(rest, io, format);
95
96
  case "many":
96
- return (await import("./decide-UOND3JAL.mjs")).runManyCommand(rest, io, format);
97
+ return (await import("./decide-XVVRKQ3V.mjs")).runManyCommand(rest, io, format);
97
98
  case "usage":
98
- return (await import("./misc-EROARLGM.mjs")).runUsageCommand(rest, io, format);
99
+ return (await import("./misc-FHOVQJ2G.mjs")).runUsageCommand(rest, io, format);
99
100
  case "config":
100
- return (await import("./config-6HS7JBVK.mjs")).runConfigCommand(rest, io, format);
101
+ return (await import("./config-REALJZDR.mjs")).runConfigCommand(rest, io, format);
101
102
  case "spec":
102
- return (await import("./spec-GIYAEVUZ.mjs")).runSpecCommand(rest, io, format);
103
+ return (await import("./spec-734MPBKB.mjs")).runSpecCommand(rest, io, format);
103
104
  case "schema":
104
- return (await import("./misc-EROARLGM.mjs")).runSchemaCommand(rest, io, format);
105
+ return (await import("./misc-FHOVQJ2G.mjs")).runSchemaCommand(rest, io, format);
106
+ case "route":
107
+ return (await import("./route-NMFOTXLI.mjs")).runRouteCommand(rest, io, format);
105
108
  case "ping":
106
- return (await import("./misc-EROARLGM.mjs")).runPingCommand(io, format);
109
+ return (await import("./misc-FHOVQJ2G.mjs")).runPingCommand(io, format);
107
110
  case "doctor":
108
- return (await import("./doctor-YCSJSTJ2.mjs")).runDoctorCommand(io, format);
111
+ return (await import("./doctor-TKFVFCZV.mjs")).runDoctorCommand(io, format);
109
112
  case "version":
110
113
  case "--version":
111
114
  case "-v":
@@ -2,10 +2,10 @@ import { createRequire as __decideRequire } from "node:module"; const require =
2
2
  import {
3
3
  parseFileRef,
4
4
  parseQuestionSet
5
- } from "./chunk-JPP6DB7K.mjs";
5
+ } from "./chunk-S5AIBUL7.mjs";
6
6
  import {
7
7
  DecisionsError
8
- } from "./chunk-PGNYF7TH.mjs";
8
+ } from "./chunk-NUIZJRI6.mjs";
9
9
 
10
10
  // src/args.ts
11
11
  import { readFileSync } from "node:fs";
@@ -145,7 +145,7 @@ function extractFormat(argv, fallback) {
145
145
  }
146
146
 
147
147
  // ../core/dist/version.js
148
- var VERSION = "0.2.0";
148
+ var VERSION = "0.3.0";
149
149
  var CLI_PACKAGE = "@garygentry/system1";
150
150
 
151
151
  export {
@@ -9,7 +9,7 @@ import {
9
9
  __require,
10
10
  __toESM,
11
11
  isDecisionsError
12
- } from "./chunk-PGNYF7TH.mjs";
12
+ } from "./chunk-NUIZJRI6.mjs";
13
13
 
14
14
  // ../../node_modules/.pnpm/yaml@2.9.1/node_modules/yaml/dist/nodes/identity.js
15
15
  var require_identity = __commonJS({
@@ -9165,6 +9165,107 @@ function escapeRegExp(text) {
9165
9165
  return text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
9166
9166
  }
9167
9167
 
9168
+ // ../core/dist/route/route.js
9169
+ var ROUTE_DEFAULTS = {
9170
+ enabled: true,
9171
+ builtin: true,
9172
+ disable: [],
9173
+ triggers: [],
9174
+ ignore: []
9175
+ };
9176
+ var both = (...parts) => `^${parts.map((p) => `(?=[\\s\\S]*?(${p}))`).join("")}`;
9177
+ var ITEMS = "tickets?|reviews?|commits?|failures?|errors?|lines|rows?|entries|items?|issues?|comments?|messages?|emails?|commands?|records?|files?|tests?|alerts?|findings?|results?|prs?|pull requests?|responses?|reports?|incidents?|warnings?|changes?|hunks?|packages?|candidates?";
9178
+ var FILE = "\\b[\\w./-]+\\.(?:jsonl|ndjson|csv|tsv|txt|log|sh)\\b";
9179
+ var BATCH = `\\b(?:each|every|all\\s+(?:the\\s+|of\\s+the\\s+)?(?:\\d+\\s+)?(?:${ITEMS})|line\\s+by\\s+line|one\\s+by\\s+one)\\b|\\b\\d{2,}\\s+(?:[\\w-]+\\s+){0,2}(?:${ITEMS})\\b`;
9180
+ var RULESET = "\\b(?:rules?|criteri(?:a|on)|requirements?|checklist|polic(?:y|ies)|guidelines?|conventions?|standards?|our\\s+bar|TASK\\.md)\\b";
9181
+ var EVIDENCE = "\\b(?:diff|uncommitted|working\\s+tree|staged|changes?|patch|pr|pull\\s+request|branch|test[-\\s]output(?:\\.log)?|test\\s+results?|TASK\\.md)\\b";
9182
+ var GATES = "commit|merge|push|ship|release|approve|deploy|land|run";
9183
+ var BUILTIN_TRIGGERS = [
9184
+ {
9185
+ // "triage every CI failure", "go through tickets.jsonl and flag any where…",
9186
+ // "which of these would pass on a rerun", "the ones complaining about…"
9187
+ name: "batch-judgement",
9188
+ pattern: both(
9189
+ // A verb glued to a hyphen is another word: "rate-limit", "score-board".
9190
+ `\\b(?:(?:classify|categori[sz]e|label|triage|bucket|grade|rate|score|rank|screen|vet|judge|assess)(?!-)|sort\\s+out|route\\s+(?:each|every|all|these|those|the)|flag\\s+(?:any|all|every|each|which|the\\s+ones|anything)|mark\\s+(?:any|all|every|each|which|the\\s+ones)|split\\s+(?:\\w+\\s+)?into|pull\\s+out\\s+(?:the|any|all|every)|tell\\s+me\\s+which|which\\s+of\\s+(?:them|these|those|the\\s+\\w+)|which\\s+ones|which\\s+(?:${ITEMS})\\s+(?:could|would|might|should|are|is|will|look|seem|need)|the\\s+ones\\s+(?:that|where|which|who|with|about|complaining|mentioning)|anything\\s+that\\s+(?:looks|seems|sounds|reads)|is\\s+each|are\\s+any\\s+of|whether\\s+each|verdicts?)\\b`,
9191
+ `${FILE}|${BATCH}`
9192
+ )
9193
+ },
9194
+ {
9195
+ // "250 packages. Which single one…", "which of the packages is the best fit"
9196
+ name: "pick-from-many",
9197
+ pattern: both("\\b(?:best\\s+(?:fit|match|one|option|choice)|which\\s+(?:single\\s+)?one|single\\s+best|pick\\s+(?:the|one)|choose\\s+(?:the|one))\\b", `${FILE}|\\b\\d{2,}\\s+(?:[\\w-]+\\s+){0,2}(?:${ITEMS}|libraries|options|helpers|modules|functions)\\b|\\bout\\s+of\\s+(?:all|the|these)\\b`)
9198
+ },
9199
+ {
9200
+ // "check the diff against these rules", "does it meet the acceptance
9201
+ // criteria", "grade each criterion pass or fail", "hold the diff to our rules"
9202
+ name: "criteria-check",
9203
+ pattern: both("\\b(?:against\\s+(?:our|the|these|this|my|each|every)?\\s*(?:[\\w-]+\\s+){0,2}(?:rules?|criteri(?:a|on)|requirements?|checklist|polic(?:y|ies)|guidelines?|conventions?|standards?|spec)|hold\\s+(?:it|this|them|the\\s+[\\w-]+(?:\\s+[\\w-]+)?)\\s+(?:up\\s+)?(?:to|against)|meets?|satisf(?:y|ies)|violat\\w*|compl(?:y|ies|iant)|pass(?:es)?\\s+(?:our|the)\\s+(?:bar|rules|checks?|checklist)|pass\\s+or\\s+fail|pass/fail|per[-\\s]criteri(?:on|a)|tick\\s+off|(?:one|a|separate)\\s+verdict|verdicts?\\s+(?:for|on)|grade\\s+(?:each|every|them|it)|(?:each|every)\\s+(?:acceptance\\s+)?(?:criteri(?:on|a)|rule|requirement|checklist\\s+item|item))\\b", RULESET)
9204
+ },
9205
+ {
9206
+ // "is the task actually done?", "am i done?", "ready to merge?", "can I ship this"
9207
+ name: "done-check",
9208
+ pattern: both("\\b(?:am\\s+i\\s+(?:actually\\s+|really\\s+)?done|are\\s+we\\s+(?:actually\\s+|really\\s+)?done|is\\s+(?:it|this|that|(?:the|my|our)\\s+\\w+(?!\\s+(?:description|message|title|name|docs?|readme|summary|text|comment)))(?:\\s+[\\w.]+){0,4}?\\s+(?:actually\\s+|really\\s+|fully\\s+|truly\\s+)?(?:done|complete|finished)|(?:ready|good|ok|safe)\\s+to\\s+(?:merge|ship|commit|push|land|release)|can\\s+(?:i|we)\\s+(?:ship|merge|land|commit|push)\\s+(?:this|it)|(?:about|going)\\s+to\\s+(?:open\\s+a\\s+pr|merge|ship|push|commit|release))\\b", `${EVIDENCE}|${FILE}`, "\\?|\\b(?:check|verify|confirm|tell\\s+me|make\\s+sure|grade|hold)\\b")
9209
+ },
9210
+ {
9211
+ // "before I commit… is it safe?", "which commands could lose data before the bot runs it"
9212
+ name: "gate-check",
9213
+ pattern: both(`\\bbefore\\s+(?:i|we|the\\s+\\w+)\\s+(?:${GATES})s?\\b`, `${RULESET}|\\b(?:safe|destructive|verdict|violat\\w*|could\\s+(?:lose|break|delete|destroy|wipe))\\b`)
9214
+ }
9215
+ ];
9216
+ var BUILTIN_IGNORE = [
9217
+ "\\b(?:don'?t|do\\s+not|without)\\s+(?:use\\s+|using\\s+)?(?:system\\s?1|decide)\\b"
9218
+ ];
9219
+ var DEFAULT_MESSAGE = "System 1 routing hint ({triggers}): the user wants closed verdicts over text. Load the system1:ask skill now, before you read the files or the diff, and let `decide` give the verdicts; do not grade them yourself. Skip this only if the user said not to use System 1.";
9220
+ function compilePattern(pattern, where) {
9221
+ try {
9222
+ return new RegExp(pattern, "i");
9223
+ } catch (error) {
9224
+ throw new DecisionsError("config-error", `${where}: invalid regular expression ${JSON.stringify(pattern)}: ${error.message}`, { pattern });
9225
+ }
9226
+ }
9227
+ function activeTriggers(config) {
9228
+ const unknown = config.disable.filter((n) => !BUILTIN_TRIGGERS.some((t) => t.name === n));
9229
+ if (unknown.length > 0) {
9230
+ throw new DecisionsError("config-error", `route.disable names unknown built-in trigger(s): ${unknown.join(", ")}. Built-ins: ${BUILTIN_TRIGGERS.map((t) => t.name).join(", ")}`);
9231
+ }
9232
+ const builtins = config.builtin ? BUILTIN_TRIGGERS.filter((t) => !config.disable.includes(t.name)) : [];
9233
+ return [
9234
+ ...builtins.map((t) => ({ ...t, source: "builtin" })),
9235
+ ...config.triggers.map((t) => ({ ...t, source: "config" }))
9236
+ ];
9237
+ }
9238
+ function route(prompt, config) {
9239
+ const triggers = activeTriggers(config);
9240
+ const ignore = [...config.builtin ? BUILTIN_IGNORE : [], ...config.ignore];
9241
+ const compiled = triggers.map((t) => ({
9242
+ ...t,
9243
+ re: compilePattern(t.pattern, `route trigger "${t.name}"`)
9244
+ }));
9245
+ const vetoes = ignore.map((p) => ({ p, re: compilePattern(p, "route.ignore") }));
9246
+ if (!config.enabled)
9247
+ return { enabled: false, matched: false, triggers: [] };
9248
+ const hits = [];
9249
+ for (const t of compiled) {
9250
+ const m = t.re.exec(prompt);
9251
+ const text = m?.[0] || m?.slice(1).filter(Boolean).join(" \u2026 ");
9252
+ if (m)
9253
+ hits.push({ name: t.name, source: t.source, text: (text ?? "").slice(0, 120) });
9254
+ }
9255
+ if (hits.length === 0)
9256
+ return { enabled: true, matched: false, triggers: [] };
9257
+ const veto = vetoes.find((v) => v.re.test(prompt));
9258
+ if (veto)
9259
+ return { enabled: true, matched: false, triggers: hits, ignoredBy: veto.p };
9260
+ const names = hits.map((h) => h.name).join(", ");
9261
+ return {
9262
+ enabled: true,
9263
+ matched: true,
9264
+ triggers: hits,
9265
+ message: (config.message ?? DEFAULT_MESSAGE).replaceAll("{triggers}", names)
9266
+ };
9267
+ }
9268
+
9168
9269
  // ../core/dist/model/validate.js
9169
9270
  function assertQuestionSet(questions) {
9170
9271
  const problems = [];
@@ -9423,7 +9524,8 @@ var DEFAULTS = {
9423
9524
  timeoutMs: DEFAULT_TIMEOUT_MS,
9424
9525
  budget: { maxCalls: 200, maxUsd: 0.05 },
9425
9526
  egress: { consent: { granted: false }, exclude: [] },
9426
- profiles: []
9527
+ profiles: [],
9528
+ route: ROUTE_DEFAULTS
9427
9529
  };
9428
9530
  function findRepoRoot(cwd) {
9429
9531
  let dir = resolve(cwd);
@@ -9470,7 +9572,8 @@ function loadConfig(options = {}) {
9470
9572
  ...stringList(repo, "egress.exclude", repoFile)
9471
9573
  ]
9472
9574
  },
9473
- profiles: [...profileList(user, userFile), ...profileList(repo, repoFile)]
9575
+ profiles: [...profileList(user, userFile), ...profileList(repo, repoFile)],
9576
+ route: readRoute(user, userFile, repo, repoFile, env)
9474
9577
  };
9475
9578
  const key = resolveApiKey(env, userDir);
9476
9579
  const session = detectSession(env);
@@ -9520,9 +9623,9 @@ function pick(key, type, ...layers2) {
9520
9623
  }
9521
9624
  return void 0;
9522
9625
  }
9523
- function pickIn(section, key, ...layers2) {
9626
+ function pickIn(section2, key, ...layers2) {
9524
9627
  for (const layer of layers2) {
9525
- const value = layer?.[section]?.[key];
9628
+ const value = layer?.[section2]?.[key];
9526
9629
  if (typeof value === "number" && value >= 0)
9527
9630
  return value;
9528
9631
  }
@@ -9580,6 +9683,69 @@ function profileList(layer, file) {
9580
9683
  };
9581
9684
  });
9582
9685
  }
9686
+ function readRoute(user, userFile, repo, repoFile, env) {
9687
+ const sections = [
9688
+ { layer: section(user, "route", userFile), file: userFile },
9689
+ { layer: section(repo, "route", repoFile), file: repoFile }
9690
+ ];
9691
+ const known = ["enabled", "builtin", "disable", "triggers", "ignore", "message"];
9692
+ const route2 = { ...ROUTE_DEFAULTS, disable: [], triggers: [], ignore: [] };
9693
+ for (const { layer, file } of sections) {
9694
+ if (!layer)
9695
+ continue;
9696
+ const extra = Object.keys(layer).filter((k) => !known.includes(k));
9697
+ if (extra.length > 0) {
9698
+ throw new DecisionsError("config-error", `${file}: unknown route key(s) ${extra.join(", ")}. Known: ${known.join(", ")}`, { file });
9699
+ }
9700
+ for (const key of ["enabled", "builtin"]) {
9701
+ const v = layer[key];
9702
+ if (v === void 0)
9703
+ continue;
9704
+ if (typeof v !== "boolean")
9705
+ throw new DecisionsError("config-error", `${file}: route.${key} must be true or false`, {
9706
+ file
9707
+ });
9708
+ route2[key] = v;
9709
+ }
9710
+ if (layer.message !== void 0) {
9711
+ if (typeof layer.message !== "string" || !layer.message.trim())
9712
+ throw new DecisionsError("config-error", `${file}: route.message must be text`, { file });
9713
+ route2.message = layer.message;
9714
+ }
9715
+ for (const key of ["disable", "ignore"]) {
9716
+ const v = layer[key];
9717
+ if (v === void 0)
9718
+ continue;
9719
+ if (!Array.isArray(v) || !v.every((x) => typeof x === "string"))
9720
+ throw new DecisionsError("config-error", `${file}: route.${key} must be a list of strings`, { file });
9721
+ route2[key].push(...v);
9722
+ }
9723
+ if (layer.triggers !== void 0)
9724
+ route2.triggers.push(...triggerList(layer.triggers, file));
9725
+ }
9726
+ if (/^(0|off|false|no)$/i.test(env.SYSTEM1_ROUTE ?? ""))
9727
+ route2.enabled = false;
9728
+ return route2;
9729
+ }
9730
+ function section(layer, key, file) {
9731
+ const value = layer?.[key];
9732
+ if (value === void 0 || value === null)
9733
+ return void 0;
9734
+ if (typeof value !== "object" || Array.isArray(value))
9735
+ throw new DecisionsError("config-error", `${file}: ${key} must be a mapping`, { file });
9736
+ return value;
9737
+ }
9738
+ function triggerList(value, file) {
9739
+ if (!Array.isArray(value))
9740
+ throw new DecisionsError("config-error", `${file}: route.triggers must be a list`, { file });
9741
+ return value.map((t, i) => {
9742
+ const { name, pattern } = t ?? {};
9743
+ if (typeof name !== "string" || !name.trim() || typeof pattern !== "string" || !pattern) {
9744
+ throw new DecisionsError("config-error", `${file}: route.triggers[${i}] needs a name and a pattern (a regular expression)`, { file });
9745
+ }
9746
+ return { name, pattern };
9747
+ });
9748
+ }
9583
9749
  function resolveApiKey(env, userDir) {
9584
9750
  const fromEnv = nonEmpty2(env.OPENROUTER_API_KEY);
9585
9751
  if (fromEnv)
@@ -19569,11 +19735,16 @@ var SpecCheckInput = typebox_exports.Object({
19569
19735
  /** Proceed past the spend guard. */
19570
19736
  confirm: typebox_exports.Optional(typebox_exports.Boolean())
19571
19737
  }, strict);
19738
+ var RouteInput = typebox_exports.Object({
19739
+ /** The user's prompt, as the harness hook received it. */
19740
+ prompt: typebox_exports.String()
19741
+ }, strict);
19572
19742
  var TOOL_SCHEMAS = {
19573
19743
  ask: AskInput,
19574
19744
  many: ManyInput,
19575
19745
  usage: UsageInput,
19576
- "spec-check": SpecCheckInput
19746
+ "spec-check": SpecCheckInput,
19747
+ route: RouteInput
19577
19748
  };
19578
19749
 
19579
19750
  // ../core/dist/tools/context.js
@@ -20223,6 +20394,31 @@ async function runAsk(ctx, rawInput) {
20223
20394
  // ../core/dist/tools/doctor.js
20224
20395
  import { accessSync, constants, statSync as statSync4 } from "node:fs";
20225
20396
  import { delimiter, join as join5 } from "node:path";
20397
+ function routeCheck(config) {
20398
+ try {
20399
+ route("", config);
20400
+ if (!config.enabled) {
20401
+ return {
20402
+ name: "route",
20403
+ status: "ok",
20404
+ detail: "routing hints are off (route.enabled or SYSTEM1_ROUTE)"
20405
+ };
20406
+ }
20407
+ const names = activeTriggers(config).map((t) => t.name);
20408
+ return {
20409
+ name: "route",
20410
+ status: "ok",
20411
+ detail: `routing hints on: ${names.length ? names.join(", ") : "no triggers"}`
20412
+ };
20413
+ } catch (error) {
20414
+ return {
20415
+ name: "route",
20416
+ status: "warn",
20417
+ detail: `routing hints are silent: ${error instanceof Error ? error.message : String(error)}`,
20418
+ fix: 'correct route: in the config file (test it with `decide route --text "\u2026"`)'
20419
+ };
20420
+ }
20421
+ }
20226
20422
  var CODEX_RULE = 'prefix_rule(pattern = ["decide"], decision = "allow")';
20227
20423
  async function runDoctor(options) {
20228
20424
  const { env } = options;
@@ -20274,6 +20470,7 @@ async function runDoctor(options) {
20274
20470
  detail: `no egress consent for ${config.repoRoot}: live calls are refused`,
20275
20471
  fix: "the user runs `decide config egress allow` in this repo, if they agree"
20276
20472
  });
20473
+ checks.push(routeCheck(config.route));
20277
20474
  let reach;
20278
20475
  try {
20279
20476
  reach = await ping({
@@ -20394,6 +20591,33 @@ function which(name, path) {
20394
20591
  return void 0;
20395
20592
  }
20396
20593
 
20594
+ // ../core/dist/tools/route.js
20595
+ function runRoute(options, rawInput) {
20596
+ const problems = checkRouteInput(rawInput);
20597
+ if (problems.length > 0) {
20598
+ throw new DecisionsError("invalid-request", `Invalid route input:
20599
+ ${problems.join("\n ")}`, {
20600
+ problems
20601
+ });
20602
+ }
20603
+ const input = rawInput;
20604
+ const config = loadConfig(options);
20605
+ const { user, repo } = config.layers;
20606
+ return {
20607
+ ...route(input.prompt, config.route),
20608
+ files: { ...user ? { user } : {}, ...repo ? { repo } : {} }
20609
+ };
20610
+ }
20611
+ function checkRouteInput(input) {
20612
+ if (typeof input !== "object" || input === null || Array.isArray(input))
20613
+ return ["/ must be an object"];
20614
+ const extra = Object.keys(input).filter((k) => k !== "prompt");
20615
+ return [
20616
+ ...typeof input.prompt === "string" ? [] : ["/prompt must be a string"],
20617
+ ...extra.map((k) => `/${k} is not allowed`)
20618
+ ];
20619
+ }
20620
+
20397
20621
  // ../core/dist/tools/spec-check.js
20398
20622
  async function runSpecCheck(ctx, rawInput) {
20399
20623
  const input = checkInput("spec-check", rawInput);
@@ -20584,6 +20808,7 @@ export {
20584
20808
  runMany,
20585
20809
  runAsk,
20586
20810
  runDoctor,
20811
+ runRoute,
20587
20812
  runSpecCheck,
20588
20813
  runUsage,
20589
20814
  resolveConnection
@@ -1,18 +1,18 @@
1
1
  import { createRequire as __decideRequire } from "node:module"; const require = __decideRequire(import.meta.url);
2
2
  import {
3
3
  typedParse
4
- } from "./chunk-NDEAV2HD.mjs";
4
+ } from "./chunk-4BSTNWLV.mjs";
5
5
  import {
6
6
  DEFAULT_EXCLUDES,
7
7
  createContext,
8
8
  loadConfig,
9
9
  repoConfigPath,
10
10
  setConsent
11
- } from "./chunk-JPP6DB7K.mjs";
11
+ } from "./chunk-S5AIBUL7.mjs";
12
12
  import {
13
13
  DecisionsError,
14
14
  emit
15
- } from "./chunk-PGNYF7TH.mjs";
15
+ } from "./chunk-NUIZJRI6.mjs";
16
16
 
17
17
  // src/commands/config.ts
18
18
  function runConfigCommand(argv, io, format) {
@@ -6,17 +6,17 @@ import {
6
6
  import {
7
7
  buildInput,
8
8
  parseDecideFlags
9
- } from "./chunk-NDEAV2HD.mjs";
9
+ } from "./chunk-4BSTNWLV.mjs";
10
10
  import {
11
11
  createContext,
12
12
  runAsk,
13
13
  runMany
14
- } from "./chunk-JPP6DB7K.mjs";
14
+ } from "./chunk-S5AIBUL7.mjs";
15
15
  import {
16
16
  DecisionsError,
17
17
  ENVELOPE_VERSION,
18
18
  emit
19
- } from "./chunk-PGNYF7TH.mjs";
19
+ } from "./chunk-NUIZJRI6.mjs";
20
20
 
21
21
  // src/commands/decide.ts
22
22
  import { readFileSync } from "node:fs";
@@ -1,10 +1,10 @@
1
1
  import { createRequire as __decideRequire } from "node:module"; const require = __decideRequire(import.meta.url);
2
2
  import {
3
3
  runDoctor
4
- } from "./chunk-JPP6DB7K.mjs";
4
+ } from "./chunk-S5AIBUL7.mjs";
5
5
  import {
6
6
  emit
7
- } from "./chunk-PGNYF7TH.mjs";
7
+ } from "./chunk-NUIZJRI6.mjs";
8
8
 
9
9
  // src/commands/doctor.ts
10
10
  import { execFile } from "node:child_process";
@@ -1,19 +1,19 @@
1
1
  import { createRequire as __decideRequire } from "node:module"; const require = __decideRequire(import.meta.url);
2
2
  import {
3
3
  typedParse
4
- } from "./chunk-NDEAV2HD.mjs";
4
+ } from "./chunk-4BSTNWLV.mjs";
5
5
  import {
6
6
  TOOL_SCHEMAS,
7
7
  createContext,
8
8
  ping,
9
9
  resolveConnection,
10
10
  runUsage
11
- } from "./chunk-JPP6DB7K.mjs";
11
+ } from "./chunk-S5AIBUL7.mjs";
12
12
  import {
13
13
  DecisionsError,
14
14
  EXIT,
15
15
  emit
16
- } from "./chunk-PGNYF7TH.mjs";
16
+ } from "./chunk-NUIZJRI6.mjs";
17
17
 
18
18
  // src/commands/misc.ts
19
19
  function runSchemaCommand(argv, io, format) {
@@ -0,0 +1,64 @@
1
+ import { createRequire as __decideRequire } from "node:module"; const require = __decideRequire(import.meta.url);
2
+ import {
3
+ typedParse
4
+ } from "./chunk-4BSTNWLV.mjs";
5
+ import {
6
+ runRoute
7
+ } from "./chunk-S5AIBUL7.mjs";
8
+ import {
9
+ DecisionsError,
10
+ emit
11
+ } from "./chunk-NUIZJRI6.mjs";
12
+
13
+ // src/commands/route.ts
14
+ import { readFileSync } from "node:fs";
15
+ var ROUTE_OPTIONS = {
16
+ text: { type: "string" },
17
+ stdin: { type: "boolean" },
18
+ hook: { type: "boolean" }
19
+ };
20
+ function runRouteCommand(argv, io, format) {
21
+ return emit(
22
+ io,
23
+ "route",
24
+ format,
25
+ () => {
26
+ const { values } = typedParse({ args: argv, options: ROUTE_OPTIONS });
27
+ const given = [values.text !== void 0, values.stdin, values.hook].filter(Boolean).length;
28
+ if (given !== 1) {
29
+ throw new DecisionsError(
30
+ "invalid-request",
31
+ "Usage: decide route --text <prompt> | --stdin | --hook (exactly one)"
32
+ );
33
+ }
34
+ const read = io.readStdin ?? (() => readFileSync(0, "utf8"));
35
+ let prompt = values.text;
36
+ let cwd = io.cwd ?? process.cwd();
37
+ if (values.stdin) prompt = read();
38
+ if (values.hook) {
39
+ const event = parseHookEvent(read());
40
+ prompt = event.prompt;
41
+ if (event.cwd) cwd = event.cwd;
42
+ }
43
+ return runRoute({ cwd, env: io.env, ...io.home ? { home: io.home } : {} }, { prompt });
44
+ },
45
+ (r, f) => f === "brief" ? r.message ?? "" : void 0
46
+ );
47
+ }
48
+ function parseHookEvent(text) {
49
+ let event;
50
+ try {
51
+ event = JSON.parse(text);
52
+ } catch {
53
+ throw new DecisionsError("invalid-request", "--hook expects a JSON hook event on stdin");
54
+ }
55
+ const { prompt, cwd } = event ?? {};
56
+ if (typeof prompt !== "string") {
57
+ throw new DecisionsError("invalid-request", "--hook: the event has no `prompt` string");
58
+ }
59
+ return { prompt, ...typeof cwd === "string" && cwd ? { cwd } : {} };
60
+ }
61
+ export {
62
+ ROUTE_OPTIONS,
63
+ runRouteCommand
64
+ };
@@ -4,7 +4,7 @@ import {
4
4
  } from "./chunk-5LVOFZF3.mjs";
5
5
  import {
6
6
  typedParse
7
- } from "./chunk-NDEAV2HD.mjs";
7
+ } from "./chunk-4BSTNWLV.mjs";
8
8
  import {
9
9
  assertExamples,
10
10
  createContext,
@@ -12,11 +12,11 @@ import {
12
12
  listSpecs,
13
13
  loadSpec,
14
14
  runSpecCheck
15
- } from "./chunk-JPP6DB7K.mjs";
15
+ } from "./chunk-S5AIBUL7.mjs";
16
16
  import {
17
17
  DecisionsError,
18
18
  emit
19
- } from "./chunk-PGNYF7TH.mjs";
19
+ } from "./chunk-NUIZJRI6.mjs";
20
20
 
21
21
  // src/commands/spec.ts
22
22
  function runSpecCommand(argv, io, format) {
@@ -4,4 +4,4 @@ import { createRequire as __decideRequire } from "node:module"; const require =
4
4
  // src/entry.ts
5
5
  import module from "node:module";
6
6
  module.enableCompileCache?.();
7
- await import("./chunks/bin-NQTRZGKT.mjs");
7
+ await import("./chunks/bin-TCIHP5PC.mjs");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@garygentry/system1",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "The `decide` CLI: typed, calibrated decisions for coding agents, hooks and CI.",
5
5
  "type": "module",
6
6
  "license": "MIT",