@garygentry/system1 0.1.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.
@@ -0,0 +1,116 @@
1
+ import { createRequire as __decideRequire } from "node:module"; const require = __decideRequire(import.meta.url);
2
+ import {
3
+ typedParse
4
+ } from "./chunk-A7ODZFMY.mjs";
5
+ import {
6
+ DEFAULT_EXCLUDES,
7
+ createContext,
8
+ loadConfig,
9
+ repoConfigPath,
10
+ setConsent
11
+ } from "./chunk-V7OTO67I.mjs";
12
+ import {
13
+ DecisionsError,
14
+ emit
15
+ } from "./chunk-7LVHD6A5.mjs";
16
+
17
+ // src/commands/config.ts
18
+ function runConfigCommand(argv, io, format) {
19
+ return emit(
20
+ io,
21
+ "config",
22
+ format,
23
+ () => body(argv, io),
24
+ (r, f) => f === "brief" ? brief(r) : void 0
25
+ );
26
+ }
27
+ function body(argv, io) {
28
+ const { values, positionals } = typedParse({
29
+ args: argv,
30
+ allowPositionals: true,
31
+ options: { confirm: { type: "boolean" }, by: { type: "string" } }
32
+ });
33
+ const [section = "show", action = "status"] = positionals;
34
+ const cwd = io.cwd ?? process.cwd();
35
+ if (section === "show") return show(io, cwd);
36
+ if (section !== "egress") {
37
+ throw new DecisionsError(
38
+ "invalid-request",
39
+ `Unknown config section "${section}". Use: show, egress`
40
+ );
41
+ }
42
+ const config = loadConfig({ cwd, env: io.env, ...io.home ? { home: io.home } : {} });
43
+ const file = repoConfigPath(config.repoRoot);
44
+ switch (action) {
45
+ case "status":
46
+ return { egress: { consent: config.egress.consent, file } };
47
+ case "allow":
48
+ if (!io.interactive && !values.confirm) {
49
+ throw new DecisionsError(
50
+ "egress-refused",
51
+ "Egress consent is the user's decision. Ask the user to run `decide config egress allow` themselves (in Claude Code: `! decide config egress allow`)."
52
+ );
53
+ }
54
+ return {
55
+ egress: {
56
+ consent: setConsent(config.repoRoot, true, values.by ?? "decide config"),
57
+ file,
58
+ changed: true
59
+ }
60
+ };
61
+ case "deny":
62
+ return {
63
+ egress: {
64
+ consent: setConsent(config.repoRoot, false, values.by ?? "decide config"),
65
+ file,
66
+ changed: true
67
+ }
68
+ };
69
+ default:
70
+ throw new DecisionsError(
71
+ "invalid-request",
72
+ `Unknown egress action "${action}". Use: status, allow, deny`
73
+ );
74
+ }
75
+ }
76
+ function show(io, cwd) {
77
+ const ctx = createContext({ ...io, cwd, env: io.env });
78
+ const { config } = ctx;
79
+ return {
80
+ repoRoot: config.repoRoot,
81
+ model: config.model,
82
+ endpoint: config.endpoint,
83
+ concurrency: config.concurrency,
84
+ budget: config.budget,
85
+ egress: {
86
+ consent: config.egress.consent,
87
+ exclude: config.egress.exclude,
88
+ defaultExcludes: DEFAULT_EXCLUDES.length
89
+ },
90
+ apiKey: config.apiKey ? `present (${config.apiKeySource})` : "absent (replay only)",
91
+ replay: config.replay,
92
+ session: config.session ?? null,
93
+ sessionOrigin: config.sessionOrigin ?? null,
94
+ files: config.layers,
95
+ specDirs: ctx.specDirs
96
+ };
97
+ }
98
+ function brief(r) {
99
+ if (!("repoRoot" in r)) {
100
+ const c2 = r.egress.consent;
101
+ return `egress consent: ${c2.granted ? `granted${c2.at ? ` ${c2.at}` : ""}` : "not granted"} (${r.egress.file})`;
102
+ }
103
+ const c = r.egress.consent;
104
+ return [
105
+ `repo: ${r.repoRoot}`,
106
+ `model: ${r.model} via ${r.endpoint}`,
107
+ `key: ${r.apiKey}${r.replay ? " \xB7 SYSTEM1_REPLAY forces replay" : ""}`,
108
+ `egress consent: ${c.granted ? `granted ${c.at ?? ""}`.trim() : "not granted \u2014 run `decide config egress allow`"}`,
109
+ `excludes: ${r.egress.defaultExcludes} default${r.egress.exclude.length ? ` + ${r.egress.exclude.join(", ")}` : ""}`,
110
+ `budget: ${r.budget.maxCalls} calls / $${r.budget.maxUsd} per request \xB7 concurrency ${r.concurrency}`,
111
+ `session: ${r.session ? `${r.session} (${r.sessionOrigin === "env" ? "SYSTEM1_SESSION" : `detected from ${r.sessionOrigin}`})` : "none"}`
112
+ ].join("\n");
113
+ }
114
+ export {
115
+ runConfigCommand
116
+ };
@@ -0,0 +1,77 @@
1
+ import { createRequire as __decideRequire } from "node:module"; const require = __decideRequire(import.meta.url);
2
+ import {
3
+ briefAsk,
4
+ briefMany
5
+ } from "./chunk-5LVOFZF3.mjs";
6
+ import {
7
+ buildInput,
8
+ parseDecideFlags
9
+ } from "./chunk-A7ODZFMY.mjs";
10
+ import {
11
+ createContext,
12
+ runAsk,
13
+ runMany
14
+ } from "./chunk-V7OTO67I.mjs";
15
+ import {
16
+ DecisionsError,
17
+ ENVELOPE_VERSION,
18
+ emit
19
+ } from "./chunk-7LVHD6A5.mjs";
20
+
21
+ // src/commands/decide.ts
22
+ import { readFileSync } from "node:fs";
23
+ var MANY_ONLY = ["dry-run", "confirm", "sort", "limit", "fields", "concurrency"];
24
+ function runAskCommand(argv, io, format) {
25
+ return emit(
26
+ io,
27
+ "ask",
28
+ format,
29
+ () => runAsk(context(io), input(argv, io, true)),
30
+ (r, f) => f === "brief" ? briefAsk(r) : void 0
31
+ );
32
+ }
33
+ function runManyCommand(argv, io, format) {
34
+ return emit(
35
+ io,
36
+ "many",
37
+ format,
38
+ () => runMany(context(io), input(argv, io)),
39
+ (r, f) => f === "brief" ? briefMany(r) : f === "jsonl" ? jsonlMany(r) : void 0
40
+ );
41
+ }
42
+ function jsonlMany(r) {
43
+ const lines = [
44
+ ...r.kept.map((row) => ({ status: "kept", ...row })),
45
+ ...r.undecided.map((row) => ({ status: "undecided", ...row })),
46
+ ...r.failed.map((f) => ({ status: "failed", ...f }))
47
+ ].map((l) => JSON.stringify(l));
48
+ const { kept: _k, undecided: _u, failed: _f, ...summary } = r;
49
+ lines.push(JSON.stringify({ v: ENVELOPE_VERSION, status: "summary", ...summary }));
50
+ return lines.join("\n");
51
+ }
52
+ function context(io) {
53
+ return createContext({ ...io, cwd: io.cwd ?? process.cwd(), env: io.env });
54
+ }
55
+ function input(argv, io, ask = false) {
56
+ const { values, positionals } = parseDecideFlags(argv);
57
+ if (ask) {
58
+ const given = MANY_ONLY.filter((flag) => values[flag] !== void 0);
59
+ if (given.length > 0) {
60
+ throw new DecisionsError(
61
+ "invalid-request",
62
+ `--${given.join(", --")} ${given.length > 1 ? "apply" : "applies"} to \`decide many\`, not \`ask\` (one state, one call).`
63
+ );
64
+ }
65
+ }
66
+ if (positionals.length > 0) {
67
+ throw new DecisionsError(
68
+ "invalid-request",
69
+ `Unexpected argument "${positionals[0]}". Did you mean --text "${positionals[0]}"?`
70
+ );
71
+ }
72
+ return buildInput(values, io.readStdin ?? (() => readFileSync(0, "utf8")), io.cwd);
73
+ }
74
+ export {
75
+ runAskCommand,
76
+ runManyCommand
77
+ };
@@ -0,0 +1,61 @@
1
+ import { createRequire as __decideRequire } from "node:module"; const require = __decideRequire(import.meta.url);
2
+ import {
3
+ runDoctor
4
+ } from "./chunk-V7OTO67I.mjs";
5
+ import {
6
+ emit
7
+ } from "./chunk-7LVHD6A5.mjs";
8
+
9
+ // src/commands/doctor.ts
10
+ import { execFile } from "node:child_process";
11
+ function runDoctorCommand(io, format) {
12
+ return emit(
13
+ io,
14
+ "doctor",
15
+ format,
16
+ () => runDoctor({
17
+ ...io,
18
+ cwd: io.cwd ?? process.cwd(),
19
+ env: io.env,
20
+ ...process.argv[1] ? { cliPath: process.argv[1] } : {},
21
+ probeVersion: (path) => probeVersion(path, io.env)
22
+ }),
23
+ (r, f) => f === "brief" ? brief(r) : void 0
24
+ );
25
+ }
26
+ function brief(r) {
27
+ const lines = [
28
+ `decide doctor: ${r.healthy ? "healthy" : "PROBLEMS FOUND"} \xB7 ${r.live ? "live ready" : "replay only"} \xB7 harness ${r.harness ?? "none"} \xB7 session ${r.session ?? "none"}`
29
+ ];
30
+ for (const c of r.checks) {
31
+ lines.push(` ${c.status.padEnd(4)} ${c.name}: ${c.detail}`);
32
+ if (c.fix && c.status !== "ok") lines.push(` fix: ${c.fix}`);
33
+ }
34
+ return lines.join("\n");
35
+ }
36
+ function probeVersion(path, env, timeoutMs = 2e3) {
37
+ return new Promise((resolve) => {
38
+ let settled = false;
39
+ const done = (value) => {
40
+ if (settled) return;
41
+ settled = true;
42
+ clearTimeout(timer);
43
+ resolve(value);
44
+ };
45
+ const child = execFile(
46
+ path,
47
+ ["version"],
48
+ { env: { ...env, SYSTEM1_NO_NPX: "1" }, timeout: timeoutMs, killSignal: "SIGKILL" },
49
+ // Empty output is passed on as "": doctor tells it apart from a failure.
50
+ (error, stdout) => done(error ? void 0 : stdout.trim().split("\n")[0] ?? "")
51
+ );
52
+ const timer = setTimeout(() => {
53
+ child.kill("SIGKILL");
54
+ done(void 0);
55
+ }, timeoutMs + 200);
56
+ });
57
+ }
58
+ export {
59
+ probeVersion,
60
+ runDoctorCommand
61
+ };
@@ -0,0 +1,78 @@
1
+ import { createRequire as __decideRequire } from "node:module"; const require = __decideRequire(import.meta.url);
2
+ import {
3
+ typedParse
4
+ } from "./chunk-A7ODZFMY.mjs";
5
+ import {
6
+ TOOL_SCHEMAS,
7
+ createContext,
8
+ ping,
9
+ resolveConnection,
10
+ runUsage
11
+ } from "./chunk-V7OTO67I.mjs";
12
+ import {
13
+ DecisionsError,
14
+ EXIT,
15
+ emit
16
+ } from "./chunk-7LVHD6A5.mjs";
17
+
18
+ // src/commands/misc.ts
19
+ function runSchemaCommand(argv, io, format) {
20
+ return emit(io, "schema", format, () => {
21
+ const [tool] = argv;
22
+ if (!tool || !(tool in TOOL_SCHEMAS)) {
23
+ throw new DecisionsError(
24
+ "invalid-request",
25
+ `Usage: decide schema <${Object.keys(TOOL_SCHEMAS).join("|")}>`
26
+ );
27
+ }
28
+ return TOOL_SCHEMAS[tool];
29
+ });
30
+ }
31
+ function runUsageCommand(argv, io, format) {
32
+ return emit(
33
+ io,
34
+ "usage",
35
+ format,
36
+ () => {
37
+ const { values } = typedParse({
38
+ args: argv,
39
+ options: { session: { type: "string" }, since: { type: "string" } }
40
+ });
41
+ const ctx = createContext({ ...io, cwd: io.cwd ?? process.cwd(), env: io.env });
42
+ return runUsage(ctx, {
43
+ ...values.session ? { session: values.session } : {},
44
+ ...values.since ? { since: values.since } : {}
45
+ });
46
+ },
47
+ (r, f) => f === "brief" ? `usage (measured): ${r.calls} call(s) \u2014 ${r.liveCalls} live, ${r.replayCalls} replayed \xB7 $${r.cost.toFixed(6)} \xB7 ${r.input_tokens} input tokens${r.session ? ` \xB7 session ${r.session}` : ""}` : void 0
48
+ );
49
+ }
50
+ async function runPingCommand(io, format) {
51
+ let failed = false;
52
+ const code = await emit(
53
+ io,
54
+ "ping",
55
+ format,
56
+ async () => {
57
+ const result = await ping(resolveConnection(io.env), io.fetch ? { fetch: io.fetch } : {});
58
+ failed = !result.ok;
59
+ if (!result.ok && format !== "brief") {
60
+ throw new DecisionsError("provider-unreachable", result.error ?? "unreachable", {
61
+ ...result
62
+ });
63
+ }
64
+ return result;
65
+ },
66
+ (r, f) => {
67
+ if (f !== "brief") return void 0;
68
+ const key = r.keyPresent ? "key: present" : "key: absent (replay only)";
69
+ return r.ok ? `decide ping: ok \u2014 ${r.model} reachable in ${r.latencyMs} ms (${key})` : `decide ping: FAILED \u2014 ${r.probe}: ${r.error} (${key})`;
70
+ }
71
+ );
72
+ return failed ? EXIT.providerError : code;
73
+ }
74
+ export {
75
+ runPingCommand,
76
+ runSchemaCommand,
77
+ runUsageCommand
78
+ };
@@ -0,0 +1,123 @@
1
+ import { createRequire as __decideRequire } from "node:module"; const require = __decideRequire(import.meta.url);
2
+ import {
3
+ briefSpecCheck
4
+ } from "./chunk-5LVOFZF3.mjs";
5
+ import {
6
+ typedParse
7
+ } from "./chunk-A7ODZFMY.mjs";
8
+ import {
9
+ assertExamples,
10
+ createContext,
11
+ exampleProblems,
12
+ listSpecs,
13
+ loadSpec,
14
+ runSpecCheck
15
+ } from "./chunk-V7OTO67I.mjs";
16
+ import {
17
+ DecisionsError,
18
+ emit
19
+ } from "./chunk-7LVHD6A5.mjs";
20
+
21
+ // src/commands/spec.ts
22
+ function runSpecCommand(argv, io, format) {
23
+ const [action = "list", ref] = argv;
24
+ const ctx = () => createContext({ ...io, cwd: io.cwd ?? process.cwd(), env: io.env });
25
+ switch (action) {
26
+ case "list":
27
+ return emit(
28
+ io,
29
+ "spec",
30
+ format,
31
+ () => ({ specs: listSpecs(ctx().specDirs) }),
32
+ (r, f) => f === "brief" ? r.specs.length ? r.specs.map(
33
+ (s) => `${s.name} [${s.origin}${s.shadowed ? ", shadowed" : ""}] ${s.error ? `INVALID: ${s.error.split("\n")[0]}` : s.description}`
34
+ ).join("\n") : "no specs found" : void 0
35
+ );
36
+ case "show":
37
+ return emit(io, "spec", format, () => {
38
+ if (!ref) throw new DecisionsError("invalid-request", "Usage: decide spec show <name|path>");
39
+ const c = ctx();
40
+ return loadSpec(ref, c.specDirs, c.cwd);
41
+ });
42
+ case "validate":
43
+ return emit(
44
+ io,
45
+ "spec",
46
+ format,
47
+ () => {
48
+ const c = ctx();
49
+ const root = c.config.repoRoot;
50
+ if (ref) {
51
+ const spec = loadSpec(ref, c.specDirs, c.cwd);
52
+ assertExamples(spec, root);
53
+ return { valid: [spec.name], invalid: [] };
54
+ }
55
+ const all = listSpecs(c.specDirs);
56
+ const invalid = all.flatMap((s) => {
57
+ if (s.error) return [{ name: s.name, error: s.error }];
58
+ const problems = exampleProblems(loadSpec(s.file, c.specDirs, c.cwd), root);
59
+ return problems.length ? [{ name: s.name, error: problems.join("\n") }] : [];
60
+ });
61
+ if (invalid.length) {
62
+ throw new DecisionsError(
63
+ "invalid-request",
64
+ `${invalid.length} invalid spec(s): ${invalid.map((i) => i.name).join(", ")}`,
65
+ { invalid }
66
+ );
67
+ }
68
+ return { valid: all.map((s) => s.name), invalid };
69
+ },
70
+ (r, f) => f === "brief" ? `valid: ${r.valid.join(", ") || "(none)"}` : void 0
71
+ );
72
+ 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
+ );
80
+ default:
81
+ return emit(io, "spec", format, () => {
82
+ throw new DecisionsError(
83
+ "invalid-request",
84
+ `Unknown spec action "${action}". Use: list, show, validate, check`
85
+ );
86
+ });
87
+ }
88
+ }
89
+ function checkInput(argv) {
90
+ const { values, positionals } = parse(argv);
91
+ const [spec, extra] = positionals;
92
+ if (!spec || extra !== void 0) {
93
+ throw new DecisionsError(
94
+ "invalid-request",
95
+ "Usage: decide spec check <name|path> [--live] [--confirm] [--model <id>]"
96
+ );
97
+ }
98
+ if (values.live && values.replay) {
99
+ throw new DecisionsError("invalid-request", "Pick one of --live, --replay");
100
+ }
101
+ return {
102
+ spec,
103
+ mode: values.live ? "record" : "replay",
104
+ ...values.confirm ? { confirm: true } : {},
105
+ ...values.model ? { model: values.model } : {}
106
+ };
107
+ }
108
+ function parse(argv) {
109
+ return typedParse({
110
+ args: argv,
111
+ allowPositionals: true,
112
+ strict: true,
113
+ options: {
114
+ live: { type: "boolean" },
115
+ replay: { type: "boolean" },
116
+ confirm: { type: "boolean" },
117
+ model: { type: "string" }
118
+ }
119
+ });
120
+ }
121
+ export {
122
+ runSpecCommand
123
+ };
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env node
2
+ import { createRequire as __decideRequire } from "node:module"; const require = __decideRequire(import.meta.url);
3
+
4
+ // src/entry.ts
5
+ import module from "node:module";
6
+ module.enableCompileCache?.();
7
+ await import("./chunks/bin-IIUCANF7.mjs");
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "@garygentry/system1",
3
+ "version": "0.1.0",
4
+ "description": "The `decide` CLI: typed, calibrated decisions for coding agents, hooks and CI.",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "author": {
8
+ "name": "Gary Gentry",
9
+ "email": "gary@garygentry.net"
10
+ },
11
+ "homepage": "https://github.com/garygentry/system1",
12
+ "keywords": [
13
+ "decisions",
14
+ "decision-model",
15
+ "jev",
16
+ "cli",
17
+ "agents",
18
+ "triage",
19
+ "classification"
20
+ ],
21
+ "repository": {
22
+ "type": "git",
23
+ "url": "https://github.com/garygentry/system1",
24
+ "directory": "packages/cli"
25
+ },
26
+ "engines": {
27
+ "node": ">=22"
28
+ },
29
+ "bin": {
30
+ "decide": "./dist/bundle/decide.mjs"
31
+ },
32
+ "files": [
33
+ "dist/bundle",
34
+ "THIRD-PARTY-NOTICES.md"
35
+ ],
36
+ "scripts": {
37
+ "build": "tsc -b && node bundle.mjs && node ../../tools/notices.mjs",
38
+ "prepublishOnly": "node ../../tools/prepublish-check.mjs"
39
+ },
40
+ "devDependencies": {
41
+ "@garygentry/system1-core": "workspace:*",
42
+ "esbuild": "^0.28.2"
43
+ },
44
+ "publishConfig": {
45
+ "access": "public"
46
+ }
47
+ }