@balpal4495/quorum 2.0.0 → 3.0.1

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.
@@ -33,13 +33,19 @@ async function guardAlreadyInitialized(target) {
33
33
  async function writeQuorumDocs(target) {
34
34
  log.section("Writing Quorum docs")
35
35
  await fs.mkdir(path.join(target, "quorum"), { recursive: true })
36
- for (const file of ["CLAUDE.md", "AGENTS.md"]) {
37
- const src = path.join(QUORUM_ROOT, "modules", file)
38
- const dest = path.join(target, "quorum", file)
39
- if (await exists(src)) {
40
- await fs.copyFile(src, dest)
41
- log.created(`quorum/${file}`)
42
- }
36
+ // Host-facing CLAUDE.md — CLI-first operational guide, not module internals
37
+ const claudeSrc = path.join(QUORUM_ROOT, "bin", "templates", "CLAUDE.md")
38
+ const claudeDest = path.join(target, "quorum", "CLAUDE.md")
39
+ if (await exists(claudeSrc)) {
40
+ await fs.copyFile(claudeSrc, claudeDest)
41
+ log.created("quorum/CLAUDE.md")
42
+ }
43
+ // AGENTS.md — module file ownership map
44
+ const agentsSrc = path.join(QUORUM_ROOT, "modules", "AGENTS.md")
45
+ const agentsDest = path.join(target, "quorum", "AGENTS.md")
46
+ if (await exists(agentsSrc)) {
47
+ await fs.copyFile(agentsSrc, agentsDest)
48
+ log.created("quorum/AGENTS.md")
43
49
  }
44
50
  await fs.copyFile(
45
51
  path.join(QUORUM_ROOT, "SETUP.md"),
@@ -0,0 +1,136 @@
1
+ import { promises as fs } from "fs"
2
+ import path from "path"
3
+ import { fileURLToPath } from "url"
4
+ import { createRequire } from "module"
5
+ import { c, log } from "../shared/colors.js"
6
+
7
+ const _require = createRequire(import.meta.url)
8
+ const __dirname = path.dirname(fileURLToPath(import.meta.url))
9
+ const QUORUM_ROOT = path.resolve(__dirname, "../..")
10
+
11
+ async function exists(p) {
12
+ return fs.access(p).then(() => true).catch(() => false)
13
+ }
14
+
15
+ async function rmrf(p) {
16
+ await fs.rm(p, { recursive: true, force: true })
17
+ }
18
+
19
+ async function readJson(p) {
20
+ return JSON.parse(await fs.readFile(p, "utf8"))
21
+ }
22
+
23
+ async function detectV1Artifacts(target) {
24
+ const artifacts = []
25
+ const vendoredModules = path.join(target, "quorum", "modules")
26
+ const vendoredEvals = path.join(target, "quorum", "evals")
27
+ if (await exists(vendoredModules)) artifacts.push({ path: vendoredModules, label: "quorum/modules/" })
28
+ if (await exists(vendoredEvals)) artifacts.push({ path: vendoredEvals, label: "quorum/evals/" })
29
+ return artifacts
30
+ }
31
+
32
+ async function removeVendoredArtifacts(artifacts) {
33
+ for (const artifact of artifacts) {
34
+ await rmrf(artifact.path)
35
+ log.ok(`Removed ${artifact.label}`)
36
+ }
37
+ }
38
+
39
+ async function ensurePackageJsonDependency(target, version) {
40
+ const pkgPath = path.join(target, "package.json")
41
+ if (!await exists(pkgPath)) return
42
+ const pkg = await readJson(pkgPath)
43
+ const already = pkg.dependencies?.["@balpal4495/quorum"] || pkg.devDependencies?.["@balpal4495/quorum"]
44
+ if (already) {
45
+ log.skipped("package.json (@balpal4495/quorum already listed)")
46
+ return
47
+ }
48
+ pkg.devDependencies = pkg.devDependencies ?? {}
49
+ pkg.devDependencies["@balpal4495/quorum"] = `^${version}`
50
+ await fs.writeFile(pkgPath, JSON.stringify(pkg, null, 2) + "\n", "utf8")
51
+ log.appended(`package.json — added @balpal4495/quorum@^${version} to devDependencies`)
52
+ }
53
+
54
+ async function refreshHostDocs(target) {
55
+ // Replace quorum/CLAUDE.md with the host-facing template (not module internals)
56
+ const claudeSrc = path.join(QUORUM_ROOT, "bin", "templates", "CLAUDE.md")
57
+ const claudeDest = path.join(target, "quorum", "CLAUDE.md")
58
+ if (await exists(claudeSrc) && await exists(claudeDest)) {
59
+ const current = await fs.readFile(claudeDest, "utf8")
60
+ // Only replace if it looks like the old module-internal version
61
+ if (current.includes("Key design decisions to preserve") || current.includes("Dependency injection throughout")) {
62
+ await fs.copyFile(claudeSrc, claudeDest)
63
+ log.ok("quorum/CLAUDE.md — replaced module-internal doc with host-facing operational guide")
64
+ } else {
65
+ log.skipped("quorum/CLAUDE.md (does not look like v1 module-internal doc — leaving as-is)")
66
+ }
67
+ }
68
+ }
69
+
70
+ async function writeVersionFile(target, version) {
71
+ await fs.writeFile(path.join(target, ".quorum-version"), version + "\n", "utf8")
72
+ log.ok(`.quorum-version — written (${version})`)
73
+ }
74
+
75
+ export async function run(argv) {
76
+ const target = process.cwd()
77
+ const dryRun = argv.includes("--dry-run")
78
+ const pkg = _require(path.join(QUORUM_ROOT, "package.json"))
79
+
80
+ console.log(c.bold("\nQuorum migrate-v2") + c.dim(` v${pkg.version}`) + (dryRun ? c.yellow(" [dry-run]") : ""))
81
+ console.log(`Target: ${c.dim(target)}\n`)
82
+
83
+ // ── Detect v1 artifacts ──────────────────────────────────────────────────
84
+ log.section("Scanning for v1 artifacts")
85
+ const artifacts = await detectV1Artifacts(target)
86
+
87
+ if (artifacts.length === 0) {
88
+ console.log(c.dim("\n No v1 vendored artifacts found (quorum/modules/, quorum/evals/)."))
89
+ console.log(c.dim(" This project may already be on v2, or was never on v1.\n"))
90
+
91
+ const hasVersionFile = await exists(path.join(target, ".quorum-version"))
92
+ if (!hasVersionFile) {
93
+ console.log(c.yellow(" No .quorum-version file found. Run 'quorum init' to initialize properly.\n"))
94
+ } else {
95
+ const currentVersion = (await fs.readFile(path.join(target, ".quorum-version"), "utf8")).trim()
96
+ console.log(c.green(` .quorum-version: ${currentVersion} ✓\n`))
97
+ }
98
+ return
99
+ }
100
+
101
+ console.log("")
102
+ for (const a of artifacts) {
103
+ console.log(` ${c.yellow("⚠")} Found: ${c.bold(a.label)}`)
104
+ }
105
+ console.log("")
106
+ console.log(c.dim(" These directories were copied by quorum init in v1 and are no longer needed."))
107
+ console.log(c.dim(" In v2, modules live in node_modules/@balpal4495/quorum."))
108
+
109
+ if (dryRun) {
110
+ console.log(c.yellow("\n [dry-run] No changes made. Re-run without --dry-run to apply.\n"))
111
+ return
112
+ }
113
+
114
+ // ── Remove vendored artifacts ────────────────────────────────────────────
115
+ log.section("Removing v1 vendored artifacts")
116
+ await removeVendoredArtifacts(artifacts)
117
+
118
+ // ── Ensure package.json lists the dependency ─────────────────────────────
119
+ log.section("Updating package.json")
120
+ await ensurePackageJsonDependency(target, pkg.version)
121
+
122
+ // ── Refresh host-facing docs ─────────────────────────────────────────────
123
+ log.section("Refreshing host docs")
124
+ await refreshHostDocs(target)
125
+
126
+ // ── Write version marker ─────────────────────────────────────────────────
127
+ log.section("Version marker")
128
+ await writeVersionFile(target, pkg.version)
129
+
130
+ console.log(`\n${c.green("✓ Migration complete.")}\n`)
131
+ console.log("Next steps:")
132
+ console.log(c.dim(" 1. npm install — install @balpal4495/quorum as a package dep"))
133
+ console.log(c.dim(" 2. quorum sync — refresh instruction blocks"))
134
+ console.log(c.dim(" 3. git rm -r quorum/modules quorum/evals 2>/dev/null — remove from git index if tracked"))
135
+ console.log("")
136
+ }
@@ -141,7 +141,7 @@ export async function run(argv) {
141
141
  if (args.subcommand === "drift") {
142
142
  console.log(`\n${c.yellow("quorum sentinel drift")} requires an LLM provider and is not available as a standalone CLI command.`)
143
143
  console.log(c.dim("\nUse the sentinelAssertions() helper in your test suite instead:"))
144
- console.log(c.dim("\n import { sentinelAssertions } from \"./quorum/modules/sentinel\""))
144
+ console.log(c.dim("\n import { sentinelAssertions } from \"@balpal4495/quorum\""))
145
145
  console.log(c.dim(" const assertions = sentinelAssertions({ llm: yourProvider })"))
146
146
  console.log(c.dim(" describe(\"sentinel\", () => { assertions.forEach(a => a()) })\n"))
147
147
  process.exit(0)
@@ -0,0 +1,97 @@
1
+ import { promises as fs } from "fs"
2
+ import path from "path"
3
+ import { fileURLToPath } from "url"
4
+ import { c, log } from "../shared/colors.js"
5
+ import { createRequire } from "module"
6
+
7
+ const _require = createRequire(import.meta.url)
8
+ const __dirname = path.dirname(fileURLToPath(import.meta.url))
9
+ const QUORUM_ROOT = path.resolve(__dirname, "../..")
10
+
11
+ async function exists(p) {
12
+ return fs.access(p).then(() => true).catch(() => false)
13
+ }
14
+
15
+ async function syncFile(target, destRelative, freshContent) {
16
+ const dest = path.join(target, destRelative)
17
+ if (!await exists(dest)) {
18
+ log.skipped(`${destRelative} (not present — run quorum init first)`)
19
+ return false
20
+ }
21
+ const existing = await fs.readFile(dest, "utf8")
22
+ const startTag = "<!-- quorum:start -->"
23
+ const endTag = "<!-- quorum:end -->"
24
+ const start = existing.indexOf(startTag)
25
+ const end = existing.indexOf(endTag)
26
+ if (start === -1 || end === -1) {
27
+ log.skipped(`${destRelative} (no quorum marker block found)`)
28
+ return false
29
+ }
30
+ const fresh = `${startTag}\n${freshContent}\n${endTag}`
31
+ const updated = existing.slice(0, start) + fresh + existing.slice(end + endTag.length)
32
+ if (updated === existing) {
33
+ log.skipped(`${destRelative} (already up to date)`)
34
+ return false
35
+ }
36
+ await fs.writeFile(dest, updated, "utf8")
37
+ log.appended(`${destRelative} (marker block refreshed)`)
38
+ return true
39
+ }
40
+
41
+ async function syncCopilotInstructions(target) {
42
+ const src = path.join(QUORUM_ROOT, ".github", "copilot-instructions.md")
43
+ if (!await exists(src)) return
44
+ const content = await fs.readFile(src, "utf8")
45
+ await syncFile(target, ".github/copilot-instructions.md", content)
46
+ }
47
+
48
+ async function syncQuorumDocs(target) {
49
+ // Replace quorum/CLAUDE.md and quorum/AGENTS.md wholesale — no marker blocks
50
+ const claudeSrc = path.join(QUORUM_ROOT, "bin", "templates", "CLAUDE.md")
51
+ const agentsSrc = path.join(QUORUM_ROOT, "modules", "AGENTS.md")
52
+ const setupSrc = path.join(QUORUM_ROOT, "SETUP.md")
53
+
54
+ for (const [src, destName] of [[claudeSrc, "quorum/CLAUDE.md"], [agentsSrc, "quorum/AGENTS.md"], [setupSrc, "quorum/SETUP.md"]]) {
55
+ const dest = path.join(target, destName)
56
+ if (!await exists(src)) continue
57
+ if (!await exists(dest)) { log.skipped(`${destName} (not present)`); continue }
58
+ const [fresh, current] = await Promise.all([fs.readFile(src, "utf8"), fs.readFile(dest, "utf8")])
59
+ if (fresh === current) { log.skipped(`${destName} (already up to date)`); continue }
60
+ await fs.writeFile(dest, fresh, "utf8")
61
+ log.appended(`${destName} (updated)`)
62
+ }
63
+ }
64
+
65
+ async function syncVersionFile(target) {
66
+ const pkg = _require(path.join(QUORUM_ROOT, "package.json"))
67
+ const dest = path.join(target, ".quorum-version")
68
+ const current = await exists(dest) ? (await fs.readFile(dest, "utf8")).trim() : null
69
+ if (current === pkg.version) {
70
+ log.skipped(`.quorum-version (already ${pkg.version})`)
71
+ return
72
+ }
73
+ await fs.writeFile(dest, pkg.version + "\n", "utf8")
74
+ log.appended(`.quorum-version — updated to ${pkg.version}`)
75
+ }
76
+
77
+ export async function run() {
78
+ const target = process.cwd()
79
+ const pkg = _require(path.join(QUORUM_ROOT, "package.json"))
80
+
81
+ console.log(c.bold("\nQuorum sync") + c.dim(` v${pkg.version}`))
82
+ console.log(`Target: ${c.dim(target)}\n`)
83
+
84
+ if (!await exists(path.join(target, ".quorum-version"))) {
85
+ console.log(c.yellow("Quorum is not initialized here. Run 'quorum init' first.\n"))
86
+ process.exit(1)
87
+ }
88
+
89
+ log.section("Refreshing instruction files")
90
+ await syncCopilotInstructions(target)
91
+
92
+ log.section("Refreshing quorum docs")
93
+ await syncQuorumDocs(target)
94
+ await syncVersionFile(target)
95
+
96
+ console.log(`\n${c.green("✓ Sync complete.")}\n`)
97
+ }
package/bin/quorum.js CHANGED
@@ -30,6 +30,9 @@ ${c.bold("Usage:")}
30
30
  ${c.cyan("quorum sentinel")} [coverage] Chronicle coverage of source files
31
31
  ${c.cyan("quorum growth")} Chronicle learning health and growth rate
32
32
  ${c.cyan("quorum evolve")} Consolidate and improve Chronicle entries (uses LLM)
33
+ ${c.cyan("quorum compass")} <subcommand> Product-direction synthesis (brief, map, pathways, bets, score)
34
+ ${c.cyan("quorum sync")} Refresh Quorum instruction blocks after npm update
35
+ ${c.cyan("quorum migrate-v2")} Migrate from v1 vendored quorum/modules/ to npm package
33
36
  ${c.cyan("quorum --version")} Print version
34
37
 
35
38
  ${c.bold("quorum advisor")} subcommands:
@@ -52,6 +55,20 @@ ${c.bold("quorum sentinel")} subcommands:
52
55
  drift (requires LLM — use sentinelAssertions() instead)
53
56
  --json Machine-readable output
54
57
 
58
+ ${c.bold("quorum migrate-v2")} flags:
59
+ --dry-run Preview what would be removed without writing
60
+
61
+ ${c.bold("quorum compass")} subcommands:
62
+ brief Summarise product direction (LLM)
63
+ map Map behaviours from code + docs (no LLM)
64
+ pathways --goal X Product pathways toward a goal (LLM)
65
+ bets Strategic big bets (LLM)
66
+ score <idea> Score a product idea (LLM)
67
+ spec <title> Generate a product brief (LLM)
68
+ opportunities List gaps from behaviour map (no LLM)
69
+ propose --from-last Stage a Chronicle entry from last artifact
70
+ outcome --entry-id X --result Y Record a bet/pathway outcome
71
+
55
72
  ${c.bold("Exit codes")} (quorum check):
56
73
  0 low / medium risk
57
74
  1 high risk
@@ -120,6 +137,24 @@ async function cli() {
120
137
  return
121
138
  }
122
139
 
140
+ if (command === "sync") {
141
+ const { run } = await import(path.join(__dirname, "commands/sync.js"))
142
+ await run(rest)
143
+ return
144
+ }
145
+
146
+ if (command === "compass") {
147
+ const { run } = await import(path.join(__dirname, "commands/compass.js"))
148
+ await run(rest)
149
+ return
150
+ }
151
+
152
+ if (command === "migrate-v2") {
153
+ const { run } = await import(path.join(__dirname, "commands/migrate-v2.js"))
154
+ await run(rest)
155
+ return
156
+ }
157
+
123
158
  console.error(`${c.red(`Unknown command: ${command}`)}`)
124
159
  console.error(`Run ${c.bold("quorum help")} for usage.`)
125
160
  process.exit(1)
@@ -0,0 +1,101 @@
1
+ # Quorum — How to use this project's memory layer
2
+
3
+ Quorum gives every AI session access to this project's approved decisions, rejected
4
+ approaches, and institutional knowledge. It runs as a CLI tool backed by a local
5
+ `.chronicle/` store.
6
+
7
+ ---
8
+
9
+ ## Start every session with memory
10
+
11
+ Before proposing or planning anything, run:
12
+
13
+ ```bash
14
+ quorum advisor brief
15
+ ```
16
+
17
+ This shows the full Chronicle summary — what the team has already learned and approved.
18
+
19
+ Then query for the specific area you are about to work in:
20
+
21
+ ```bash
22
+ quorum advisor query "topic of the work"
23
+ ```
24
+
25
+ If relevant entries exist, treat them as ground truth. **Refuted entries are hard stops** —
26
+ do not retry a refuted approach without explicitly surfacing the failure reason to the user.
27
+
28
+ ---
29
+
30
+ ## Check designs before coding
31
+
32
+ For any significant change, run a preflight check first:
33
+
34
+ ```bash
35
+ quorum check \
36
+ --outcome "what you want to achieve" \
37
+ --design "how you plan to do it"
38
+ ```
39
+
40
+ Exit codes: `0` = low/medium risk — proceed. `1` = high risk — human review first.
41
+ `2` = critical — stop and get explicit sign-off.
42
+
43
+ Auth, payments, crypto, database migrations, PII, and data deletion always trigger
44
+ elevated risk, regardless of how the design is framed.
45
+
46
+ ---
47
+
48
+ ## Propose what was learned
49
+
50
+ When a significant decision is made or an approach is ruled out, stage a Chronicle
51
+ proposal for human review:
52
+
53
+ The Council stages proposals automatically after deliberation. You can also stage
54
+ them manually by following the Chronicle proposal template in SETUP.md.
55
+
56
+ ```bash
57
+ quorum commit --list # see all pending proposals
58
+ quorum commit <id> # approve and index a proposal
59
+ ```
60
+
61
+ **Never call `oracle.commit()` autonomously.** Only propose. A human must approve.
62
+
63
+ ---
64
+
65
+ ## Keep memory healthy
66
+
67
+ ```bash
68
+ quorum growth # is Chronicle actually growing?
69
+ quorum evolve # consolidate duplicate or stale entries (uses LLM)
70
+ quorum sentinel coverage # which source files have Chronicle entries?
71
+ ```
72
+
73
+ ---
74
+
75
+ ## Chronicle structure
76
+
77
+ ```
78
+ .chronicle/
79
+ committed/ ← approved entries, indexed and searchable (commit to git)
80
+ proposals/ ← staged entries awaiting your approval (do not commit)
81
+ SUMMARY.md ← auto-generated context, rebuilt on every commit
82
+ ```
83
+
84
+ Commit `.chronicle/committed/` so every teammate and every new AI session starts with
85
+ the same accumulated knowledge. Never commit `.chronicle/proposals/`.
86
+
87
+ ---
88
+
89
+ ## CLI quick reference
90
+
91
+ ```bash
92
+ quorum advisor brief # full Chronicle summary, no LLM
93
+ quorum advisor query "topic" # keyword search, no LLM
94
+ quorum advisor "plain-language question" # synthesised answer via LLM
95
+ quorum check --outcome "..." --design "..." # instant risk triage
96
+ quorum commit --list # review pending proposals
97
+ quorum commit <id> # approve a Chronicle entry
98
+ quorum growth # Chronicle learning health
99
+ quorum evolve # consolidate stale entries (LLM)
100
+ quorum sync # refresh Quorum instruction blocks after npm update
101
+ ```
package/modules/README.md CHANGED
@@ -1,12 +1,12 @@
1
- # Advisor · Oracle · Jury · Council · Sentinel
1
+ # Advisor · Oracle · Jury · Council · Sentinel · Compass
2
2
 
3
- Five portable modules for the knowledge and reasoning layer of any agentic workflow.
4
- Drop the `modules/` folder into your project and wire up the dependencies.
3
+ Six portable modules for the knowledge, reasoning, and product-direction layer of any agentic workflow.
5
4
 
6
5
  ```
7
6
  Advisor → plain-language questions answered from Chronicle
8
7
  Oracle → Jury → Council → human gate → Executor
9
8
  Sentinel → coverage + drift + PR coverage map
9
+ Compass → product-direction synthesis (behaviours, pathways, bets, scoring)
10
10
  ```
11
11
 
12
12
  ---
@@ -20,6 +20,7 @@ Sentinel → coverage + drift + PR coverage map
20
20
  | **Jury** | Evaluate a design against Oracle evidence — produces a confidence score | Yes |
21
21
  | **Council** | Adversarial validation via parallel advisor/reviewer fan-out — produces a verdict | Yes |
22
22
  | **Sentinel** | Chronicle coverage reporting, drift detection, and PR coverage maps | Optional |
23
+ | **Compass** | Product-direction synthesis from Chronicle + codebase — behaviours, opportunities, pathways, bets, idea scoring | Optional |
23
24
 
24
25
  ---
25
26
 
@@ -91,6 +92,40 @@ You can substitute any vector store and embedder by implementing the `VectorStor
91
92
 
92
93
  ---
93
94
 
95
+ ## TypeScript runtime requirement
96
+
97
+ Quorum ships TypeScript source (`.ts` files). Programmatic imports require a
98
+ TS-aware runtime or bundler. Plain `node` will not work without a loader.
99
+
100
+ **Supported runtimes:**
101
+
102
+ ```bash
103
+ # tsx (recommended — zero config)
104
+ npx tsx your-script.ts
105
+
106
+ # ts-node
107
+ npx ts-node --esm your-script.ts
108
+
109
+ # Bun
110
+ bun your-script.ts
111
+
112
+ # Vitest / Jest with ts transform — works out of the box in test files
113
+ ```
114
+
115
+ **Bundlers:** esbuild, Vite, Rollup, webpack — all supported with standard TS config.
116
+
117
+ **Plain Node.js** (no TS runtime): use the CLI instead:
118
+
119
+ ```bash
120
+ quorum advisor "question"
121
+ quorum check --outcome "..." --design "..."
122
+ ```
123
+
124
+ The CLI is always available after `npm install -g @balpal4495/quorum` and requires no
125
+ TS loader. It is the recommended interface for most host-project use cases.
126
+
127
+ ---
128
+
94
129
  ## TypeScript
95
130
 
96
131
  Requires TypeScript 4.7+ and `zod` v3.
@@ -109,8 +144,10 @@ Recommended `tsconfig.json` settings:
109
144
 
110
145
  ## Quick start
111
146
 
147
+ ### npm users
148
+
112
149
  ```typescript
113
- import { setup } from "./modules/setup"
150
+ import { setup } from "@balpal4495/quorum"
114
151
 
115
152
  // The simplest entry point — wires all modules from one call
116
153
  const { oracle, evaluate, deliberate, ask } = await setup({ llm: myLLMProvider })
@@ -123,12 +160,22 @@ const answer = await ask("what did the team decide about authentication?")
123
160
  const evidence = await oracle.query("authentication patterns in this codebase")
124
161
  ```
125
162
 
163
+ ### Quorum repo contributors
164
+
165
+ Working directly inside the Quorum source tree? Import from the local path instead:
166
+
167
+ ```typescript
168
+ import { setup } from "./modules/setup"
169
+
170
+ const { oracle, evaluate, deliberate, ask } = await setup({ llm: myLLMProvider })
171
+ ```
172
+
126
173
  ### Manual wiring (without setup())
127
174
 
128
175
  ```typescript
129
- import { createOracleClient, xenovaEmbed, createLanceDBStore } from "./modules/oracle"
130
- import { evaluate } from "./modules/jury"
131
- import { deliberate } from "./modules/council"
176
+ import { createOracleClient, xenovaEmbed, createLanceDBStore } from "@balpal4495/quorum/oracle"
177
+ import { evaluate } from "@balpal4495/quorum/jury"
178
+ import { deliberate } from "@balpal4495/quorum/council"
132
179
 
133
180
  // Wire Oracle manually
134
181
  const oracle = createOracleClient({
@@ -190,7 +237,7 @@ if (verdict.satisfied) {
190
237
  The Advisor is the plain-language interface to Chronicle. Use it to answer questions rather than to evaluate designs. It is a **read-only** path — it never calls `oracle.propose()` or `oracle.commit()`.
191
238
 
192
239
  ```typescript
193
- import { ask } from "./modules/advisor"
240
+ import { ask } from "@balpal4495/quorum/advisor"
194
241
 
195
242
  const answer = await ask(
196
243
  { question: "What did the team decide about session handling?", evidence },
@@ -231,7 +278,7 @@ Advisor validates its own answer before returning. If `confidence < 0.7` or `blo
231
278
  The `LLMProvider` type is a simple function. Wire it to any provider:
232
279
 
233
280
  ```typescript
234
- import type { LLMProvider } from "./modules/shared/types"
281
+ import type { LLMProvider } from "@balpal4495/quorum"
235
282
 
236
283
  // OpenAI example
237
284
  const openaiProvider: LLMProvider = async (messages, model = "gpt-4o") => {
@@ -276,7 +323,7 @@ interface JuryOutput {
276
323
  Before the LLM runs, Jury executes a deterministic preflight:
277
324
 
278
325
  ```typescript
279
- import { runPreflight } from "./modules/jury"
326
+ import { runPreflight } from "@balpal4495/quorum/jury"
280
327
 
281
328
  const preflight = runPreflight(outcome, design, evidence)
282
329
  // preflight.touches_sensitive_area