create-quorum-router 0.1.5

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 sakamoto-sann
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,89 @@
1
+ # create-quorum-router
2
+
3
+ Create a local QuorumRouter project scaffold.
4
+
5
+ QuorumRouter is **MIT-licensed open source**. Commercial and production use are
6
+ permitted under the MIT License.
7
+
8
+ ## Usage
9
+
10
+ ```bash
11
+ npx --yes create-quorum-router@latest my-quorum-router-demo
12
+ cd my-quorum-router-demo
13
+ deno --version
14
+ deno task smoke
15
+ deno task intake
16
+ ```
17
+
18
+ Current package version: `create-quorum-router@0.1.5`. Releases are published
19
+ from an immutable Git tag through GitHub Actions OIDC Trusted Publishing.
20
+
21
+ ## What the generated project supports
22
+
23
+ `deno task smoke` is deterministic fixture-only and does not call a provider
24
+ API.
25
+
26
+ `deno task intake` is the first real setup command. It detects local provider
27
+ wrappers, checks OAuth/session status, runs safe list-only model inventory where
28
+ possible, writes redacted local health artifacts under `out/`, and recommends
29
+ the next command.
30
+
31
+ ```bash
32
+ deno task check
33
+ deno task smoke
34
+ deno task intake
35
+ deno task auth:status
36
+ deno task auth:login
37
+ deno task auth:logout
38
+ deno task models:list
39
+ deno task health
40
+ ```
41
+
42
+ Real provider use is OAuth/session/wrapper-first:
43
+
44
+ ```bash
45
+ RUN_EXTERNAL_MODEL_DOGFOOD=1 deno task route:once --prompt "Review this README for risky claims."
46
+ RUN_EXTERNAL_MODEL_DOGFOOD=1 deno task route:once --prompt "https://github.com/sakamoto-sann/quorum-router review this repo's launch readiness."
47
+ # GitHub URL prompts fetch bounded repository context before invoking the selected provider.
48
+ # Only use this with repositories you are allowed to send to that provider.
49
+ RUN_EXTERNAL_MODEL_DOGFOOD=1 deno task best-route --prompt "Choose the safest launch copy."
50
+ RUN_EXTERNAL_MODEL_DOGFOOD=1 RUN_EXPERIMENTAL_AGENT_CHAT=1 deno task agent-chat --prompt "Review this launch plan."
51
+ ```
52
+
53
+ `auth:login` does not ask for API keys as the primary path. If OAuth/browser
54
+ login is not wired in the generated scaffold, it fails closed and tells the user
55
+ to use an installed provider CLI login, then rerun `deno task intake`.
56
+
57
+ ## Private/manual env fallback
58
+
59
+ Generic env fallback exists only as an explicit private/manual fallback with
60
+ `QUORUM_ROUTER_AUTH_MODE=env`. It is never used silently, and it is not the
61
+ preferred public dogfood path.
62
+
63
+ Do not commit `.env`, `router.config.local.json`, `.quorum-router/`, or `out/`.
64
+ Do not paste tokens into chat/logs.
65
+
66
+ ## Runtime boundaries
67
+
68
+ - Best Route/direct is production-ready best-answer routing.
69
+ - Conversation-only `agent_chat` is explicit opt-in.
70
+ - SafeLoop-backed Agent Chat can perform the verified local repository execution
71
+ slice only when separately configured with signed policy and distinct
72
+ approval.
73
+ - The generated scaffold does not enable mutation by default.
74
+ - No service-role runtime.
75
+ - No live Supabase Agent Bus runtime writes.
76
+ - Public launch requires the repository verification, package tarball, registry
77
+ readback, and clean-room NPX scaffold checks to pass.
78
+
79
+ ## CLI
80
+
81
+ ```bash
82
+ create-quorum-router <dir>
83
+ create-quorum-router <dir> --template basic
84
+ create-quorum-router <dir> --force
85
+ create-quorum-router --help
86
+ create-quorum-router --version
87
+ ```
88
+
89
+ The CLI refuses to overwrite a non-empty directory unless `--force` is passed.
@@ -0,0 +1,161 @@
1
+ #!/usr/bin/env node
2
+ const fs = require("fs");
3
+ const path = require("path");
4
+ const { spawnSync } = require("child_process");
5
+
6
+ const VERSION = "0.1.5";
7
+ const SUPPORTED_TEMPLATES = new Set(["basic"]);
8
+
9
+ function usage() {
10
+ return `create-quorum-router ${VERSION}
11
+
12
+ Usage:
13
+ create-quorum-router <dir>
14
+ create-quorum-router <dir> --template basic
15
+ create-quorum-router <dir> --force
16
+ create-quorum-router --help
17
+ create-quorum-router --version
18
+
19
+ Creates a local QuorumRouter project scaffold. The scaffold does not fetch remote
20
+ code, install dependencies, ask for credentials, write secrets, enable process
21
+ adapters, or configure live runtime services. Fixture smoke is deterministic;
22
+ external provider dogfood and GitHub URL context fetching are explicit manual
23
+ opt-in paths.`;
24
+ }
25
+
26
+ function hasCommand(command) {
27
+ const result = spawnSync(command, ["--version"], { stdio: "ignore" });
28
+ return !result.error && result.status === 0;
29
+ }
30
+
31
+ function parseArgs(argv) {
32
+ const args = [...argv];
33
+ const options = { template: "basic", force: false, dir: undefined };
34
+ while (args.length > 0) {
35
+ const arg = args.shift();
36
+ if (arg === "--help" || arg === "-h") return { help: true };
37
+ if (arg === "--version" || arg === "-v") return { version: true };
38
+ if (arg === "--force") {
39
+ options.force = true;
40
+ continue;
41
+ }
42
+ if (arg === "--template") {
43
+ const template = args.shift();
44
+ if (!template) throw new Error("--template requires a value");
45
+ options.template = template;
46
+ continue;
47
+ }
48
+ if (arg && arg.startsWith("--template=")) {
49
+ options.template = arg.slice("--template=".length);
50
+ continue;
51
+ }
52
+ if (arg && arg.startsWith("-")) throw new Error(`unknown option: ${arg}`);
53
+ if (options.dir) throw new Error(`unexpected extra argument: ${arg}`);
54
+ options.dir = arg;
55
+ }
56
+ return options;
57
+ }
58
+
59
+ function copyRecursive(from, to) {
60
+ const stat = fs.statSync(from);
61
+ if (stat.isDirectory()) {
62
+ fs.mkdirSync(to, { recursive: true });
63
+ for (const entry of fs.readdirSync(from)) {
64
+ const targetEntry = entry === "gitignore" ? ".gitignore" : entry;
65
+ copyRecursive(path.join(from, entry), path.join(to, targetEntry));
66
+ }
67
+ return;
68
+ }
69
+ fs.copyFileSync(from, to);
70
+ }
71
+
72
+ function isNonEmptyDirectory(dir) {
73
+ try {
74
+ const stat = fs.statSync(dir);
75
+ return stat.isDirectory() && fs.readdirSync(dir).length > 0;
76
+ } catch (error) {
77
+ if (error && error.code === "ENOENT") return false;
78
+ throw error;
79
+ }
80
+ }
81
+
82
+ function main() {
83
+ const parsed = parseArgs(process.argv.slice(2));
84
+ if (parsed.help) {
85
+ console.log(usage());
86
+ return;
87
+ }
88
+ if (parsed.version) {
89
+ console.log(VERSION);
90
+ return;
91
+ }
92
+ if (!parsed.dir) {
93
+ throw new Error("target directory is required\n\n" + usage());
94
+ }
95
+ if (!SUPPORTED_TEMPLATES.has(parsed.template)) {
96
+ throw new Error(`unsupported template: ${parsed.template}`);
97
+ }
98
+
99
+ const targetDir = path.resolve(process.cwd(), parsed.dir);
100
+ if (isNonEmptyDirectory(targetDir) && !parsed.force) {
101
+ throw new Error(
102
+ `refusing to overwrite non-empty directory: ${targetDir}\n` +
103
+ "Pass --force to overwrite template files in this directory.",
104
+ );
105
+ }
106
+
107
+ const templateDir = path.join(__dirname, "..", "templates", parsed.template);
108
+ fs.mkdirSync(targetDir, { recursive: true });
109
+ copyRecursive(templateDir, targetDir);
110
+ fs.mkdirSync(path.join(targetDir, "out"), { recursive: true });
111
+ fs.writeFileSync(path.join(targetDir, "out", ".gitkeep"), "");
112
+
113
+ console.log(`Created QuorumRouter project in ${targetDir}`);
114
+ console.log("");
115
+ console.log("Next steps:");
116
+ console.log(` cd ${path.relative(process.cwd(), targetDir) || "."}`);
117
+ console.log(" deno task check");
118
+ console.log(" deno task smoke");
119
+ console.log(" deno task intake");
120
+ console.log(" deno task auth:status");
121
+ console.log(" deno task models:list");
122
+ console.log(" deno task health");
123
+ if (!hasCommand("deno")) {
124
+ console.log("");
125
+ console.log("Warning: Deno was not found on PATH.");
126
+ console.log(
127
+ "Install Deno before running the tasks above: brew install deno, or use the official installer at deno.com/install.",
128
+ );
129
+ console.log("Then verify with: deno --version");
130
+ }
131
+ console.log(
132
+ " # Optional one-shot real provider dogfood after intake reports a usable OAuth/session/wrapper provider:",
133
+ );
134
+ console.log(
135
+ ' RUN_EXTERNAL_MODEL_DOGFOOD=1 deno task route:once --prompt "Review this README for risky claims."',
136
+ );
137
+ console.log(" # Optional Best Route over local wrappers:");
138
+ console.log(
139
+ ' RUN_EXTERNAL_MODEL_DOGFOOD=1 deno task best-route --prompt "Choose the safest launch copy."',
140
+ );
141
+ console.log(
142
+ " # Optional conversation-only Agent Chat stays explicit opt-in:",
143
+ );
144
+ console.log(
145
+ ' RUN_EXTERNAL_MODEL_DOGFOOD=1 RUN_EXPERIMENTAL_AGENT_CHAT=1 deno task agent-chat --prompt "Review this launch plan."',
146
+ );
147
+ console.log("");
148
+ console.log(
149
+ "Note: deno task smoke is deterministic fixture-only and does not call a provider API.",
150
+ );
151
+ console.log(
152
+ "Note: intake is the first real setup command; route:once/best-route are manual opt-in real provider dogfood; env fallback requires QUORUM_ROUTER_AUTH_MODE=env.",
153
+ );
154
+ }
155
+
156
+ try {
157
+ main();
158
+ } catch (error) {
159
+ console.error(error && error.message ? error.message : String(error));
160
+ process.exit(1);
161
+ }
package/package.json ADDED
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "create-quorum-router",
3
+ "version": "0.1.5",
4
+ "description": "Create a local QuorumRouter project.",
5
+ "license": "MIT",
6
+ "bin": {
7
+ "create-quorum-router": "bin/create-quorum-router.js"
8
+ },
9
+ "files": [
10
+ "bin",
11
+ "templates",
12
+ "README.md",
13
+ "LICENSE"
14
+ ],
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "git+https://github.com/sakamoto-sann/quorum-router.git"
18
+ }
19
+ }
@@ -0,0 +1,168 @@
1
+ # QuorumRouter generated workspace
2
+
3
+ This generated workspace contains the MIT-licensed QuorumRouter current release.
4
+ npm latest targets v0.1.5.
5
+
6
+ QuorumRouter is **MIT**. It is **open source**. Commercial and production use
7
+ are permitted under the MIT License.
8
+
9
+ ## Security and runtime boundaries
10
+
11
+ - MIT-licensed open source; commercial and production use are permitted.
12
+ - `deno task smoke` is fixture-only and credential-free.
13
+ - `deno task intake` is the first real setup command.
14
+ - Real provider use is OAuth/session/wrapper-first.
15
+ - API key env fallback is private/manual only and never used silently.
16
+ - Never commit `.env`, `router.config.local.json`, `provider_config.json`,
17
+ `.quorum-router/`, or `out/` traces.
18
+ - Never paste tokens into chat/logs.
19
+ - Conversation-only `agent_chat` is explicit opt-in.
20
+ - SafeLoop-backed production repository execution is not enabled by this
21
+ generated scaffold; it requires external signed policy and distinct approval.
22
+ - No service-role runtime.
23
+ - No live Supabase runtime writes.
24
+ - No live Supabase Agent Bus runtime writes.
25
+ - Best Route/direct is the production-ready best-answer routing path.
26
+ - `agent-chat` is read-only explicit opt-in only.
27
+
28
+ ## First launch
29
+
30
+ Prerequisite: install Deno before running scaffold tasks. Verify with:
31
+
32
+ ```bash
33
+ deno --version
34
+ ```
35
+
36
+ ```bash
37
+ deno task smoke
38
+ deno task intake
39
+ deno task auth:status
40
+ deno task models:list
41
+ deno task health
42
+ ```
43
+
44
+ `smoke` proves the local scaffold runs with deterministic fixtures only. It does
45
+ **not** call a real provider API.
46
+
47
+ `intake` detects local provider wrappers, checks OAuth/session status, runs safe
48
+ model inventory/list-only probes where possible, writes local health traces
49
+ under `out/`, and recommends the next command.
50
+
51
+ In short: intake is the first real setup command before `route:once`,
52
+ `best-route`, or read-only `agent-chat`.
53
+
54
+ ## Real provider dogfood commands
55
+
56
+ Run only after `intake` reports a usable OAuth/session/wrapper provider:
57
+
58
+ ```bash
59
+ RUN_EXTERNAL_MODEL_DOGFOOD=1 deno task route:once --prompt "Review this README for risky claims."
60
+ RUN_EXTERNAL_MODEL_DOGFOOD=1 deno task best-route --prompt "Choose the safest launch copy."
61
+ RUN_EXTERNAL_MODEL_DOGFOOD=1 RUN_EXPERIMENTAL_AGENT_CHAT=1 deno task agent-chat --prompt "Review this launch plan."
62
+ ```
63
+
64
+ Behavior:
65
+
66
+ - `route:once` requires `RUN_EXTERNAL_MODEL_DOGFOOD=1`.
67
+ - `best-route` requires `RUN_EXTERNAL_MODEL_DOGFOOD=1`.
68
+ - `agent-chat` requires both `RUN_EXTERNAL_MODEL_DOGFOOD=1` and
69
+ `RUN_EXPERIMENTAL_AGENT_CHAT=1`.
70
+ - Live Agent Chat requires at least two distinct working provider/model
71
+ identities. It passes the bounded transcript to alternating models, prints
72
+ each response and `replying to` lineage as it arrives, and stores turns in
73
+ `out/agent-chat-trace.json`.
74
+ - Set `QUORUM_ROUTER_AGENT_CHAT_MAX_TURNS` from 2–12 (default 6) to bound calls.
75
+ - Default auth mode is OAuth/session/wrapper-first.
76
+ - In auto mode, `route:once` prefers list-verified wrapper models and safely
77
+ tries the next wrapper when an invocation fails; the trace records the failed
78
+ attempt and `fallback_used`.
79
+ - Explicit provider/model selection never falls back to a different wrapper.
80
+ - Env fallback is used only with `QUORUM_ROUTER_AUTH_MODE=env` and local private
81
+ credential environment.
82
+ - Traces are redacted and written under `out/`.
83
+ - When the prompt contains a GitHub repository URL like
84
+ `https://github.com/owner/repo`, `route:once`, `best-route`, and read-only
85
+ `agent-chat` fetch a bounded, prioritized set of repository text files first,
86
+ quote them as untrusted JSON data, and record context coverage in the trace.
87
+ Only use this with repositories you are allowed to send to the selected
88
+ provider.
89
+
90
+ ### Forced wrapper provider/model selection
91
+
92
+ Use these only when you want a specific local wrapper/model. The scaffold fails
93
+ closed if the requested provider or model is unavailable; it never silently
94
+ falls back to OpenAI/Codex or private env fallback unless
95
+ `QUORUM_ROUTER_AUTH_MODE=env` is explicit.
96
+
97
+ ```bash
98
+ QUORUM_ROUTER_AUTH_MODE=wrapper \
99
+ QUORUM_ROUTER_PROVIDER_LABEL=grok-cli \
100
+ QUORUM_ROUTER_PROVIDER_MODEL=grok-build \
101
+ RUN_EXTERNAL_MODEL_DOGFOOD=1 \
102
+ deno task route:once --prompt "Review this README for risky claims."
103
+
104
+ QUORUM_ROUTER_AUTH_MODE=wrapper \
105
+ QUORUM_ROUTER_PROVIDER_LABEL=grok-cli \
106
+ QUORUM_ROUTER_PROVIDER_MODEL=grok-composer-2.5-fast \
107
+ RUN_EXTERNAL_MODEL_DOGFOOD=1 \
108
+ deno task route:once --prompt "Review this README for usability."
109
+ ```
110
+
111
+ Supported provider aliases include `grok-cli`, `grok`, `xai`, `xAI`, `OpenAI`,
112
+ `codex-cli`, `claude-code`, `gemini-cli`, `devin-cli`, and `qwen-cli`. Wrapper
113
+ invocations use argv arrays, closed stdin, timeout guards, and sanitized
114
+ stdout/stderr; CLI banners or auth/runtime errors are not accepted as valid
115
+ model answers.
116
+
117
+ ## Auth and inventory
118
+
119
+ ```bash
120
+ deno task auth:status
121
+ deno task auth:login
122
+ deno task auth:logout
123
+ deno task models:list
124
+ ```
125
+
126
+ `auth:login` does not ask for API keys as the primary path. If OAuth/browser
127
+ login is not wired in this scaffold, it fails closed and tells you to use an
128
+ installed provider CLI login, then rerun `deno task intake`.
129
+
130
+ Browser/device login handling is safe-by-default: the scaffold does not open a
131
+ browser automatically. Provider CLIs own their own login flows.
132
+
133
+ ## Private/manual env fallback
134
+
135
+ Generic OpenAI-compatible env fallback exists only as an explicit private
136
+ fallback:
137
+
138
+ ```bash
139
+ QUORUM_ROUTER_AUTH_MODE=env \
140
+ RUN_EXTERNAL_MODEL_DOGFOOD=1 \
141
+ deno task route:once --prompt "Review this README change."
142
+ ```
143
+
144
+ Credential values must come from your local environment or secret manager. Do
145
+ not paste them into chat/logs and do not commit `.env`.
146
+
147
+ ## Generated files
148
+
149
+ - `main.ts` — deterministic fixture smoke only.
150
+ - `deno.json` — generated task surface.
151
+ - `README.md` — practical first-launch guide.
152
+ - `.gitignore` — excludes `.env`, `out/`, `router.config.local.json`,
153
+ `provider_config.json`, and `.quorum-router/`.
154
+ - `router.config.example.json` — non-secret example boundaries.
155
+ - `src/cli.ts` — command dispatcher.
156
+ - `src/intake.ts` — first-run onboarding.
157
+ - `src/auth.ts`, `src/auth_oauth.ts`, `src/auth_session.ts`,
158
+ `src/auth_env_fallback.ts` — auth/session/fallback boundaries.
159
+ - `src/provider_registry.ts`, `src/model_inventory.ts`, `src/wrapper_client.ts`,
160
+ `src/provider_client.ts` — provider discovery and safe invocation.
161
+ - `src/best_route.ts`, `src/agent_chat.ts` — gated dogfood commands.
162
+ - `src/trace.ts`, `src/redact.ts`, `src/schema.ts`, `src/fixture_smoke.ts` —
163
+ trace/redaction/schema/fixture support.
164
+ - `out/.gitkeep` — local output directory placeholder.
165
+
166
+ Public Product Hunt/X launch remains blocked until the user personally runs a
167
+ local pre-release workspace and approves release continuation. This scaffold
168
+ does not publish npm, create a GitHub release, or mutate tags/dist-tags.
@@ -0,0 +1,19 @@
1
+ {
2
+ "lock": false,
3
+ "imports": {
4
+ "zod": "https://deno.land/x/zod@v3.23.8/mod.ts"
5
+ },
6
+ "tasks": {
7
+ "check": "deno check main.ts src/*.ts",
8
+ "smoke": "deno run main.ts",
9
+ "intake": "deno run --allow-read --allow-write --allow-env --allow-net --allow-run=grok,codex,claude,gemini,qwen,devin src/cli.ts intake",
10
+ "auth:status": "deno run --allow-read --allow-env --allow-run=grok,codex,claude,gemini,qwen,devin src/cli.ts auth:status",
11
+ "auth:login": "deno run src/cli.ts auth:login",
12
+ "auth:logout": "deno run --allow-read --allow-write --allow-env src/cli.ts auth:logout",
13
+ "models:list": "deno run --allow-read --allow-write --allow-env --allow-run=grok,codex,claude,gemini,qwen,devin src/cli.ts models:list",
14
+ "health": "deno run --allow-read --allow-write --allow-env --allow-run=grok,codex,claude,gemini,qwen,devin src/cli.ts health",
15
+ "route:once": "deno run --allow-read --allow-write --allow-env --allow-net --allow-run=grok,codex,claude,gemini,qwen,devin src/cli.ts route:once",
16
+ "best-route": "deno run --allow-read --allow-write --allow-env --allow-net --allow-run=grok,codex,claude,gemini,qwen,devin src/cli.ts best-route",
17
+ "agent-chat": "deno run --allow-read --allow-write --allow-env --allow-net --allow-run=grok,codex,claude,gemini,qwen,devin src/cli.ts agent-chat"
18
+ }
19
+ }
@@ -0,0 +1,5 @@
1
+ .env
2
+ out/
3
+ router.config.local.json
4
+ provider_config.json
5
+ .quorum-router/
@@ -0,0 +1,3 @@
1
+ import { runFixtureSmoke } from "./src/fixture_smoke.ts";
2
+
3
+ await runFixtureSmoke();
File without changes
@@ -0,0 +1,15 @@
1
+ {
2
+ "auth_mode": "auto",
3
+ "preferred_path": "oauth-session-wrapper-first",
4
+ "env_fallback": {
5
+ "enabled_by": "QUORUM_ROUTER_AUTH_MODE=env",
6
+ "usage": "private manual fallback only"
7
+ },
8
+ "runtime_boundaries": {
9
+ "best_route_direct": "production-ready best-answer routing",
10
+ "agent_chat": "experimental explicit opt-in only",
11
+ "production_autonomous_runtime": false,
12
+ "live_supabase_agent_bus_writes": false,
13
+ "service_role_runtime": false
14
+ }
15
+ }