@garygentry/system1 0.3.1 → 0.4.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.
@@ -70,7 +70,13 @@ var EXIT = {
70
70
  egressRefused: 3,
71
71
  budgetGuard: 4,
72
72
  providerError: 5,
73
- replayMiss: 6
73
+ replayMiss: 6,
74
+ /**
75
+ * The check ran and did not pass: `spec check --strict` (an example missed),
76
+ * or `spec lint` (an error-level finding or invalid spec; with `--strict`, any
77
+ * warning).
78
+ */
79
+ checkFailed: 7
74
80
  };
75
81
  var BY_CODE = {
76
82
  "invalid-request": EXIT.usage,
@@ -145,7 +151,7 @@ function extractFormat(argv, fallback) {
145
151
  }
146
152
 
147
153
  // ../core/dist/version.js
148
- var VERSION = "0.3.1";
154
+ var VERSION = "0.4.0";
149
155
  var CLI_PACKAGE = "@garygentry/system1";
150
156
 
151
157
  export {
@@ -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-O6BSAJIH.mjs";
5
+ } from "./chunk-QYUSJUFX.mjs";
6
6
  import {
7
7
  DecisionsError
8
- } from "./chunk-JD7HVXW5.mjs";
8
+ } from "./chunk-WZIVOY5Q.mjs";
9
9
 
10
10
  // src/args.ts
11
11
  import { readFileSync } from "node:fs";
@@ -23,9 +23,11 @@ var DECIDE_OPTIONS = {
23
23
  staged: { type: "boolean" },
24
24
  text: { type: "string" },
25
25
  stdin: { type: "boolean" },
26
+ exclude: { type: "string", multiple: true },
26
27
  "allow-outside": { type: "boolean" },
27
28
  split: { type: "string" },
28
29
  keep: { type: "string", multiple: true },
30
+ "keep-any": { type: "string", multiple: true },
29
31
  sort: { type: "string" },
30
32
  limit: { type: "string" },
31
33
  fields: { type: "string" },
@@ -104,8 +106,10 @@ function buildInput(values, readStdin, cwd = process.cwd()) {
104
106
  );
105
107
  }
106
108
  if (sources.length) input.sources = sources;
109
+ set("exclude", values.exclude?.length ? values.exclude : void 0);
107
110
  set("split", values.split);
108
111
  set("keep", values.keep?.length ? values.keep : void 0);
112
+ set("keepAny", values["keep-any"]?.length ? values["keep-any"] : void 0);
109
113
  set("sort", values.sort);
110
114
  set("limit", int(values.limit, "--limit"));
111
115
  set(
@@ -1,18 +1,20 @@
1
1
  import { createRequire as __decideRequire } from "node:module"; const require = __decideRequire(import.meta.url);
2
2
  import {
3
3
  typedParse
4
- } from "./chunk-X2CYN5PB.mjs";
4
+ } from "./chunk-XNRV73UE.mjs";
5
5
  import {
6
6
  DEFAULT_EXCLUDES,
7
+ activeTriggers,
8
+ allProfiles,
7
9
  createContext,
8
10
  loadConfig,
9
11
  repoConfigPath,
10
12
  setConsent
11
- } from "./chunk-O6BSAJIH.mjs";
13
+ } from "./chunk-QYUSJUFX.mjs";
12
14
  import {
13
15
  DecisionsError,
14
16
  emit
15
- } from "./chunk-JD7HVXW5.mjs";
17
+ } from "./chunk-WZIVOY5Q.mjs";
16
18
 
17
19
  // src/commands/config.ts
18
20
  function runConfigCommand(argv, io, format) {
@@ -49,12 +51,17 @@ function body(argv, io) {
49
51
  if (!io.interactive && !values.confirm) {
50
52
  throw new DecisionsError(
51
53
  "egress-refused",
52
- "Egress consent is the user's decision. Ask the user to run `decide config egress allow` themselves (in Claude Code: `! decide config egress allow`)."
54
+ "Egress consent is the user's decision. An agent must not grant it, with or without --confirm: show the user this message instead. The user grants it by typing `decide config egress allow` in a terminal at the repo root. If they run it through their agent prompt's shell escape instead (not as a chat message), there is no terminal, so they add --confirm to say the decision is theirs."
53
55
  );
54
56
  }
55
57
  return {
56
58
  egress: {
57
- consent: setConsent(config.repoRoot, true, values.by ?? "decide config"),
59
+ // Record which route granted it: a terminal, or --confirm without one.
60
+ consent: setConsent(
61
+ config.repoRoot,
62
+ true,
63
+ values.by ?? (io.interactive ? "decide config" : "decide config --confirm")
64
+ ),
58
65
  file,
59
66
  changed: true
60
67
  }
@@ -82,6 +89,7 @@ function show(io, cwd) {
82
89
  model: config.model,
83
90
  endpoint: config.endpoint,
84
91
  concurrency: config.concurrency,
92
+ timeoutMs: config.timeoutMs,
85
93
  budget: config.budget,
86
94
  egress: {
87
95
  consent: config.egress.consent,
@@ -92,8 +100,15 @@ function show(io, cwd) {
92
100
  replay: config.replay,
93
101
  session: config.session ?? null,
94
102
  sessionOrigin: config.sessionOrigin ?? null,
103
+ /**
104
+ * The profiles in effect for the ids the config files set, one per id: an
105
+ * override of a built-in shows once. Built-ins nobody overrides are not repeated.
106
+ */
107
+ profiles: allProfiles(config).filter((p) => config.profiles.some((c) => c.id === p.id)),
108
+ route: config.route,
95
109
  files: config.layers,
96
- specDirs: ctx.specDirs
110
+ specDirs: ctx.specDirs,
111
+ warnings: config.warnings
97
112
  };
98
113
  }
99
114
  function brief(r) {
@@ -106,12 +121,24 @@ function brief(r) {
106
121
  `repo: ${r.repoRoot}`,
107
122
  `model: ${r.model} via ${r.endpoint}`,
108
123
  `key: ${r.apiKey}${r.replay ? " \xB7 SYSTEM1_REPLAY forces replay" : ""}`,
109
- `egress consent: ${c.granted ? `granted ${c.at ?? ""}`.trim() : "not granted \u2014 run `decide config egress allow`"}`,
124
+ `egress consent: ${c.granted ? `granted ${c.at ?? ""}`.trim() : "not granted (the user grants it; see `decide doctor`)"}`,
110
125
  `excludes: ${r.egress.defaultExcludes} default${r.egress.exclude.length ? ` + ${r.egress.exclude.join(", ")}` : ""}`,
111
- `budget: ${r.budget.maxCalls} calls / $${r.budget.maxUsd} per request \xB7 concurrency ${r.concurrency}`,
112
- `session: ${r.session ? `${r.session} (${r.sessionOrigin === "env" ? "SYSTEM1_SESSION" : `detected from ${r.sessionOrigin}`})` : "none"}`
126
+ `budget: ${r.budget.maxCalls} calls / $${r.budget.maxUsd} per request \xB7 concurrency ${r.concurrency} \xB7 timeout ${r.timeoutMs} ms`,
127
+ ...r.profiles.length ? [`profiles: ${r.profiles.map((p) => p.id).join(", ")}`] : [],
128
+ `route: ${routeLine(r.route)}`,
129
+ `session: ${r.session ? `${r.session} (${r.sessionOrigin === "env" ? "SYSTEM1_SESSION" : `detected from ${r.sessionOrigin}`})` : "none"}`,
130
+ ...r.warnings.length ? [`ignored: ${r.warnings.join("; ")}`] : []
113
131
  ].join("\n");
114
132
  }
133
+ function routeLine(route) {
134
+ if (!route.enabled) return "off";
135
+ try {
136
+ const names = activeTriggers(route).map((t) => t.name);
137
+ return `on \xB7 ${names.join(", ") || "no triggers"}`;
138
+ } catch (error) {
139
+ return `invalid (${error instanceof Error ? error.message : String(error)})`;
140
+ }
141
+ }
115
142
  export {
116
143
  CONFIG_OPTIONS,
117
144
  runConfigCommand
@@ -2,21 +2,21 @@ import { createRequire as __decideRequire } from "node:module"; const require =
2
2
  import {
3
3
  briefAsk,
4
4
  briefMany
5
- } from "./chunk-5LVOFZF3.mjs";
5
+ } from "./chunk-FU3D2MBS.mjs";
6
6
  import {
7
7
  buildInput,
8
8
  parseDecideFlags
9
- } from "./chunk-X2CYN5PB.mjs";
9
+ } from "./chunk-XNRV73UE.mjs";
10
10
  import {
11
11
  createContext,
12
12
  runAsk,
13
13
  runMany
14
- } from "./chunk-O6BSAJIH.mjs";
14
+ } from "./chunk-QYUSJUFX.mjs";
15
15
  import {
16
16
  DecisionsError,
17
17
  ENVELOPE_VERSION,
18
18
  emit
19
- } from "./chunk-JD7HVXW5.mjs";
19
+ } from "./chunk-WZIVOY5Q.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-O6BSAJIH.mjs";
4
+ } from "./chunk-QYUSJUFX.mjs";
5
5
  import {
6
6
  emit
7
- } from "./chunk-JD7HVXW5.mjs";
7
+ } from "./chunk-WZIVOY5Q.mjs";
8
8
 
9
9
  // src/commands/doctor.ts
10
10
  import { execFile } from "node:child_process";
@@ -1,19 +1,22 @@
1
1
  import { createRequire as __decideRequire } from "node:module"; const require = __decideRequire(import.meta.url);
2
2
  import {
3
3
  typedParse
4
- } from "./chunk-X2CYN5PB.mjs";
4
+ } from "./chunk-XNRV73UE.mjs";
5
5
  import {
6
6
  TOOL_SCHEMAS,
7
7
  createContext,
8
+ loadConfig,
8
9
  ping,
10
+ probeUrl,
9
11
  resolveConnection,
10
12
  runUsage
11
- } from "./chunk-O6BSAJIH.mjs";
13
+ } from "./chunk-QYUSJUFX.mjs";
12
14
  import {
13
15
  DecisionsError,
14
16
  EXIT,
15
- emit
16
- } from "./chunk-JD7HVXW5.mjs";
17
+ emit,
18
+ isDecisionsError
19
+ } from "./chunk-WZIVOY5Q.mjs";
17
20
 
18
21
  // src/commands/misc.ts
19
22
  function runSchemaCommand(argv, io, format) {
@@ -55,7 +58,20 @@ async function runPingCommand(io, format) {
55
58
  "ping",
56
59
  format,
57
60
  async () => {
58
- const result = await ping(resolveConnection(io.env), io.fetch ? { fetch: io.fetch } : {});
61
+ const { config, configError } = connection(io);
62
+ try {
63
+ probeUrl(config);
64
+ } catch {
65
+ throw new DecisionsError(
66
+ "config-error",
67
+ `endpoint ${config.endpoint} is not a URL: correct SYSTEM1_ENDPOINT or \`endpoint\` in the config file`,
68
+ { endpoint: config.endpoint }
69
+ );
70
+ }
71
+ const result = {
72
+ ...await ping(config, io.fetch ? { fetch: io.fetch } : {}),
73
+ ...configError ? { configError } : {}
74
+ };
59
75
  failed = !result.ok;
60
76
  if (!result.ok && format !== "brief") {
61
77
  throw new DecisionsError("provider-unreachable", result.error ?? "unreachable", {
@@ -67,11 +83,28 @@ async function runPingCommand(io, format) {
67
83
  (r, f) => {
68
84
  if (f !== "brief") return void 0;
69
85
  const key = r.keyPresent ? "key: present" : "key: absent (replay only)";
70
- return r.ok ? `decide ping: ok \u2014 ${r.model} reachable in ${r.latencyMs} ms (${key})` : `decide ping: FAILED \u2014 ${r.probe}: ${r.error} (${key})`;
86
+ const line = r.ok ? `decide ping: ok \u2014 ${r.model} reachable in ${r.latencyMs} ms (${key})` : `decide ping: FAILED \u2014 ${r.probe}: ${r.error} (${key})`;
87
+ return r.configError ? `${line}
88
+ config not loaded, so this used the environment only: ${r.configError}` : line;
71
89
  }
72
90
  );
73
91
  return failed ? EXIT.providerError : code;
74
92
  }
93
+ function connection(io) {
94
+ try {
95
+ const config = loadConfig({
96
+ cwd: io.cwd ?? process.cwd(),
97
+ env: io.env,
98
+ ...io.home ? { home: io.home } : {}
99
+ });
100
+ const { endpoint, model, apiKey, replay } = config;
101
+ return { config: { endpoint, model, apiKey, replay } };
102
+ } catch (error) {
103
+ if (isDecisionsError(error) && error.code === "config-error")
104
+ return { config: resolveConnection(io.env), configError: error.message };
105
+ throw error;
106
+ }
107
+ }
75
108
  export {
76
109
  USAGE_OPTIONS,
77
110
  runPingCommand,
@@ -0,0 +1,144 @@
1
+ import { createRequire as __decideRequire } from "node:module"; const require = __decideRequire(import.meta.url);
2
+ import {
3
+ typedParse
4
+ } from "./chunk-XNRV73UE.mjs";
5
+ import {
6
+ createContext,
7
+ runOpportunitiesAdd,
8
+ runOpportunitiesCheck,
9
+ runOpportunitiesList
10
+ } from "./chunk-QYUSJUFX.mjs";
11
+ import {
12
+ DecisionsError,
13
+ emit
14
+ } from "./chunk-WZIVOY5Q.mjs";
15
+
16
+ // src/commands/opportunities.ts
17
+ import { readFileSync } from "node:fs";
18
+ import { resolve } from "node:path";
19
+ var OPPORTUNITIES_OPTIONS = {
20
+ file: { type: "string" },
21
+ keep: { type: "string", multiple: true },
22
+ sort: { type: "string" },
23
+ limit: { type: "string" },
24
+ fields: { type: "string" }
25
+ };
26
+ var USAGE = "Usage: decide opportunities add --file <candidates.json> | list [--keep \u2026] [--sort \u2026] [--limit N] [--fields a,b] | check";
27
+ function runOpportunitiesCommand(argv, io, format) {
28
+ const [action, ...rest] = argv;
29
+ const ctx = () => createContext({ ...io, cwd: io.cwd ?? process.cwd(), env: io.env });
30
+ const cwd = io.cwd ?? process.cwd();
31
+ switch (action) {
32
+ case "add":
33
+ return emit(
34
+ io,
35
+ "opportunities",
36
+ format,
37
+ () => {
38
+ const { values } = parse(rest, ["file"]);
39
+ if (!values.file) throw new DecisionsError("invalid-request", USAGE);
40
+ return runOpportunitiesAdd(ctx(), {
41
+ candidates: readCandidates(resolve(cwd, values.file), values.file)
42
+ });
43
+ },
44
+ (r, f) => f === "brief" ? `decide opportunities add: ${r.added.length} added \xB7 ${r.updated.length} updated \xB7 ${r.staled.length} marked stale \xB7 ${r.total} in ${r.file}` : void 0
45
+ );
46
+ case "list":
47
+ return emit(
48
+ io,
49
+ "opportunities",
50
+ format,
51
+ () => {
52
+ const { values } = parse(rest, ["keep", "sort", "limit", "fields"]);
53
+ if (values.limit !== void 0 && !/^\d+$/.test(values.limit)) {
54
+ throw new DecisionsError("invalid-request", "--limit must be a whole number");
55
+ }
56
+ return runOpportunitiesList(ctx(), {
57
+ ...values.keep?.length ? { keep: values.keep } : {},
58
+ ...values.sort ? { sort: values.sort } : {},
59
+ ...values.limit !== void 0 ? { limit: Number(values.limit) } : {},
60
+ ...values.fields ? {
61
+ fields: values.fields.split(",").map((s) => s.trim()).filter(Boolean)
62
+ } : {}
63
+ });
64
+ },
65
+ (r, f) => f === "brief" ? briefList(r) : void 0
66
+ );
67
+ case "check":
68
+ return emit(
69
+ io,
70
+ "opportunities",
71
+ format,
72
+ () => {
73
+ parse(rest, []);
74
+ return runOpportunitiesCheck(ctx());
75
+ },
76
+ (r, f) => f === "brief" ? r.exists ? `decide opportunities check: valid \xB7 ${r.entries} entr${r.entries === 1 ? "y" : "ies"}${Object.keys(r.byStatus).length ? ` (${Object.entries(r.byStatus).map(([s, n]) => `${n} ${s}`).join(", ")})` : ""} \xB7 ${r.file}` : `decide opportunities check: no backlog yet (${r.file})` : void 0
77
+ );
78
+ default:
79
+ return emit(io, "opportunities", format, () => {
80
+ throw new DecisionsError("invalid-request", USAGE);
81
+ });
82
+ }
83
+ }
84
+ function parse(argv, allowed) {
85
+ const options = Object.fromEntries(allowed.map((k) => [k, OPPORTUNITIES_OPTIONS[k]]));
86
+ return typedParse({ args: argv, options, strict: true });
87
+ }
88
+ function readCandidates(path, ref) {
89
+ let text;
90
+ try {
91
+ text = readFileSync(path, "utf8");
92
+ } catch {
93
+ throw new DecisionsError("invalid-request", `--file: cannot read ${ref}`);
94
+ }
95
+ let value;
96
+ try {
97
+ value = JSON.parse(text);
98
+ } catch (error) {
99
+ throw new DecisionsError(
100
+ "invalid-request",
101
+ `--file ${ref}: not JSON (${error.message})`
102
+ );
103
+ }
104
+ if (Array.isArray(value)) return value;
105
+ if (value && typeof value === "object" && "candidates" in value) {
106
+ const extra = Object.keys(value).filter((k) => k !== "candidates");
107
+ if (extra.length) {
108
+ throw new DecisionsError(
109
+ "invalid-request",
110
+ `--file ${ref}: unknown key(s) ${extra.join(", ")}; only "candidates" is read`
111
+ );
112
+ }
113
+ return value.candidates;
114
+ }
115
+ throw new DecisionsError(
116
+ "invalid-request",
117
+ `--file ${ref}: expected a JSON array of candidates, or {"candidates": [...]}`
118
+ );
119
+ }
120
+ function briefList(r) {
121
+ const lines = [
122
+ `decide opportunities list: ${r.opportunities.length} shown \xB7 ${r.matched} matched \xB7 ${r.total} total \xB7 savings projected`
123
+ ];
124
+ for (const o of r.opportunities) {
125
+ const where = o.location ? `${o.location.path}${o.location.lines ? `:${o.location.lines.start}-${o.location.lines.end}` : ""}` : "";
126
+ const saving = o.projected ? ` \xB7 $${o.projected.savingUsd} per ${o.projected.per} (projected)` : "";
127
+ const head = [
128
+ o.id,
129
+ o.status,
130
+ o.mode,
131
+ o.shape,
132
+ o.benefit,
133
+ o.risk ? `risk ${o.risk.level}` : void 0
134
+ ].filter(Boolean).join(" \xB7 ");
135
+ lines.push(` ${head}${saving}${where ? ` ${where}` : ""}`);
136
+ if (o.mechanism) lines.push(` ${o.mechanism}`);
137
+ if (o.statusReason) lines.push(` ${o.status}: ${o.statusReason}`);
138
+ }
139
+ return lines.join("\n");
140
+ }
141
+ export {
142
+ OPPORTUNITIES_OPTIONS,
143
+ runOpportunitiesCommand
144
+ };
@@ -1,14 +1,14 @@
1
1
  import { createRequire as __decideRequire } from "node:module"; const require = __decideRequire(import.meta.url);
2
2
  import {
3
3
  typedParse
4
- } from "./chunk-X2CYN5PB.mjs";
4
+ } from "./chunk-XNRV73UE.mjs";
5
5
  import {
6
6
  runRoute
7
- } from "./chunk-O6BSAJIH.mjs";
7
+ } from "./chunk-QYUSJUFX.mjs";
8
8
  import {
9
9
  DecisionsError,
10
10
  emit
11
- } from "./chunk-JD7HVXW5.mjs";
11
+ } from "./chunk-WZIVOY5Q.mjs";
12
12
 
13
13
  // src/commands/route.ts
14
14
  import { readFileSync } from "node:fs";
@@ -1,22 +1,25 @@
1
1
  import { createRequire as __decideRequire } from "node:module"; const require = __decideRequire(import.meta.url);
2
2
  import {
3
- briefSpecCheck
4
- } from "./chunk-5LVOFZF3.mjs";
3
+ briefSpecCheck,
4
+ briefSpecLint
5
+ } from "./chunk-FU3D2MBS.mjs";
5
6
  import {
6
7
  typedParse
7
- } from "./chunk-X2CYN5PB.mjs";
8
+ } from "./chunk-XNRV73UE.mjs";
8
9
  import {
9
10
  assertExamples,
10
11
  createContext,
11
12
  exampleProblems,
12
13
  listSpecs,
13
14
  loadSpec,
14
- runSpecCheck
15
- } from "./chunk-O6BSAJIH.mjs";
15
+ runSpecCheck,
16
+ runSpecLint
17
+ } from "./chunk-QYUSJUFX.mjs";
16
18
  import {
17
19
  DecisionsError,
20
+ EXIT,
18
21
  emit
19
- } from "./chunk-JD7HVXW5.mjs";
22
+ } from "./chunk-WZIVOY5Q.mjs";
20
23
 
21
24
  // src/commands/spec.ts
22
25
  function runSpecCommand(argv, io, format) {
@@ -70,29 +73,71 @@ function runSpecCommand(argv, io, format) {
70
73
  (r, f) => f === "brief" ? `valid: ${r.valid.join(", ") || "(none)"}` : void 0
71
74
  );
72
75
  case "check":
73
- return emit(
74
- io,
75
- "spec",
76
- format,
77
- () => runSpecCheck(ctx(), checkInput(argv.slice(1))),
78
- (r, f) => f === "brief" ? briefSpecCheck(r) : void 0
79
- );
76
+ return check(argv.slice(1), io, format, ctx);
77
+ case "lint":
78
+ return lint(argv.slice(1), io, format, ctx);
80
79
  default:
81
80
  return emit(io, "spec", format, () => {
82
81
  throw new DecisionsError(
83
82
  "invalid-request",
84
- `Unknown spec action "${action}". Use: list, show, validate, check`
83
+ `Unknown spec action "${action}". Use: list, show, validate, lint, check`
85
84
  );
86
85
  });
87
86
  }
88
87
  }
88
+ async function check(argv, io, format, ctx) {
89
+ let failed = false;
90
+ const code = await emit(
91
+ io,
92
+ "spec",
93
+ format,
94
+ async () => {
95
+ const result = await runSpecCheck(ctx(), checkInput(argv));
96
+ failed = !result.passed;
97
+ return result;
98
+ },
99
+ (r, f) => f === "brief" ? briefSpecCheck(r) : void 0
100
+ );
101
+ return code === EXIT.ok && failed && parse(argv).values.strict ? EXIT.checkFailed : code;
102
+ }
103
+ async function lint(argv, io, format, ctx) {
104
+ let failed = false;
105
+ let strict = false;
106
+ const code = await emit(
107
+ io,
108
+ "spec",
109
+ format,
110
+ () => {
111
+ const { values, positionals } = typedParse({
112
+ args: argv,
113
+ allowPositionals: true,
114
+ strict: true,
115
+ options: LINT_OPTIONS
116
+ });
117
+ const [spec, extra] = positionals;
118
+ if (extra !== void 0) {
119
+ throw new DecisionsError(
120
+ "invalid-request",
121
+ "Usage: decide spec lint [name|path] [--strict]"
122
+ );
123
+ }
124
+ strict = values.strict ?? false;
125
+ const result = runSpecLint(ctx(), spec ? { spec } : {});
126
+ failed = !result.passed || strict && result.counts.warnings > 0;
127
+ return result;
128
+ },
129
+ (r, f) => f === "brief" ? briefSpecLint(r) : void 0
130
+ );
131
+ return code === EXIT.ok && failed ? EXIT.checkFailed : code;
132
+ }
133
+ var LINT_OPTIONS = { strict: { type: "boolean" } };
89
134
  function checkInput(argv) {
90
135
  const { values, positionals } = parse(argv);
91
136
  const [spec, extra] = positionals;
92
137
  if (!spec || extra !== void 0) {
93
138
  throw new DecisionsError(
94
139
  "invalid-request",
95
- "Usage: decide spec check <name|path> [--live] [--confirm] [--model <id>]"
140
+ "Usage: decide spec check <name|path> [--live] [--confirm] [--model <id>] [--strict]"
96
141
  );
97
142
  }
98
143
  if (values.live && values.replay) {
@@ -109,7 +154,8 @@ var SPEC_OPTIONS = {
109
154
  live: { type: "boolean" },
110
155
  replay: { type: "boolean" },
111
156
  confirm: { type: "boolean" },
112
- model: { type: "string" }
157
+ model: { type: "string" },
158
+ strict: { type: "boolean" }
113
159
  };
114
160
  function parse(argv) {
115
161
  return typedParse({
@@ -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-FN3DZQV3.mjs");
7
+ await import("./chunks/bin-TIEUYIP3.mjs");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@garygentry/system1",
3
- "version": "0.3.1",
3
+ "version": "0.4.0",
4
4
  "description": "The `decide` CLI: typed, calibrated decisions for coding agents, hooks and CI.",
5
5
  "type": "module",
6
6
  "license": "MIT",