@balpal4495/quorum 3.3.0 → 3.3.2

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,117 @@
1
+ # Project Guidelines
2
+
3
+ ## Architecture
4
+
5
+ This project uses six portable reasoning modules: **Advisor**, **Oracle**, **Jury**, **Council**, **Sentinel**, and **Compass**.
6
+ They form the knowledge, validation, and product-direction layer for all agentic work in this codebase.
7
+
8
+ ```
9
+ Advisor → plain-language Chronicle queries
10
+ Oracle → Jury → Council → human gate → Executor
11
+ Sentinel → coverage + drift
12
+ Compass → product-direction synthesis (behaviours, pathways, bets, scoring)
13
+ ```
14
+
15
+ Source: `modules/` — see [modules/README.md](modules/README.md) for full API reference.
16
+
17
+ ---
18
+
19
+ ## Chronicle — the persistent knowledge store
20
+
21
+ Chronicle lives at `.chronicle/` and is the institutional memory of this codebase.
22
+ Every prior decision, investigation finding, and outcome is stored there.
23
+
24
+ **Always query Oracle before proposing a solution.** Treat existing entries as ground truth for what has been tried, what worked, and what failed.
25
+
26
+ ```typescript
27
+ const evidence = await oracle.query("describe what you're about to do")
28
+ // Use evidence to inform your proposal before proceeding
29
+ ```
30
+
31
+ **Never call `oracle.commit()` without explicit human approval.**
32
+ `oracle.propose()` writes a pending file. A human must call `oracle.commit(proposalId)` to index it.
33
+ There are no auto-commits. Do not attempt to bypass this gate.
34
+
35
+ ---
36
+
37
+ ## Module responsibilities
38
+
39
+ | Module | What it does | LLM? |
40
+ |---|---|---|
41
+ | `ask()` | Plain-language question answered from Chronicle — validates internally, retries up to 2× | Yes |
42
+ | `oracle.query()` | Retrieves relevant Chronicle entries by semantic + BM25 search | No |
43
+ | `oracle.propose()` | Stages a new entry for human review | No |
44
+ | `oracle.commit()` | Indexes an approved entry — human-triggered only | No |
45
+ | `jury.evaluate()` | Scores a design against evidence across 4 dimensions | Yes |
46
+ | `council.deliberate()` | Adversarial validation via advisor/reviewer fan-out | Yes |
47
+ | `sentinel` | Coverage reporting, drift detection, and PR coverage maps | Optional |
48
+ | `compass` | Product-direction synthesis — behaviours, opportunities, pathways, bets, idea scoring | Optional |
49
+
50
+ ---
51
+
52
+ ## Setup
53
+
54
+ ```typescript
55
+ import { setup } from "@balpal4495/quorum"
56
+
57
+ const { oracle, evaluate, deliberate, ask, compass } = await setup({ llm: yourProvider })
58
+ ```
59
+
60
+ `setup()` creates Chronicle directories, warms the embedder, and wires all dependencies.
61
+ Call it once at application startup.
62
+
63
+ ---
64
+
65
+ ## Routing rules
66
+
67
+ After `jury.evaluate()`:
68
+
69
+ | `recommendation` | Action |
70
+ |---|---|
71
+ | `proceed` | Pass to `council.deliberate()` |
72
+ | `investigate-more` | Return to Detective with `juryOutput.gaps` |
73
+ | `redesign` | Return to Designer |
74
+
75
+ After `council.deliberate()`:
76
+
77
+ | `satisfied` | `recommendation` | Action |
78
+ |---|---|---|
79
+ | `true` | `proceed` | Human gate → Executor |
80
+ | `false` | `redesign` | Return to Designer with `verdict` as feedback |
81
+ | `false` | `investigate-more` | Return to Detective with `juryOutput.gaps` |
82
+
83
+ ---
84
+
85
+ ## Rules for AI agents
86
+
87
+ - **Evidence first.** Query Oracle before proposing any design or implementation.
88
+ - **No auto-commits.** Never call `oracle.commit()` autonomously. Only propose.
89
+ - **Cite entries.** When referencing Chronicle findings, use the entry ID (e.g. `[abc-123]`).
90
+ - **Respect refuted entries.** A `refuted` entry means this was tried and failed — surface the failure reason, don't ignore it.
91
+ - **Fail loudly.** Jury and Council throw on bad LLM output. Do not swallow errors or default to passing scores.
92
+ - **These modules are the portable core.** Detective, Designer, Executor, and Validator are application-specific — do not add them here.
93
+
94
+ ---
95
+
96
+ ## CLI quick reference
97
+
98
+ ```bash
99
+ quorum advisor brief # full Chronicle summary, no LLM
100
+ quorum advisor query "topic" # keyword search, no LLM
101
+ quorum advisor "plain-language question" # synthesised answer via LLM
102
+ quorum check --outcome "..." --design "..." # instant risk triage
103
+ quorum commit --list # review pending proposals
104
+ quorum commit <id> # approve a Chronicle entry
105
+ quorum compass map # map current product behaviours (no LLM)
106
+ quorum compass brief # product-direction summary (LLM)
107
+ quorum compass pathways --goal "..." # generate product pathways (LLM)
108
+ quorum compass score "idea" # score a product idea (LLM)
109
+ ```
110
+
111
+ ---
112
+
113
+ ## Build and test
114
+
115
+ ```bash
116
+ npx vitest run modules/ evals/
117
+ ```
package/GEMINI.md ADDED
@@ -0,0 +1,73 @@
1
+ # Quorum — Gemini Context
2
+
3
+ > This file is optional. It is only active when Google Gemini CLI is installed and
4
+ > `GEMINI_API_KEY` is set. Projects without Gemini CLI configured can ignore it.
5
+
6
+ ## Your role in this project
7
+
8
+ You are a supporting AI in the Quorum codebase. Claude Code is the primary agent — it handles
9
+ tool execution, file edits, complex reasoning, and final decisions.
10
+
11
+ You are called in two modes:
12
+
13
+ 1. **Assistant mode** — Claude needs large-context analysis it can't efficiently do itself:
14
+ summarise many files, trace a pattern across the codebase, answer questions that require
15
+ holding the entire repo in memory at once.
16
+
17
+ 2. **Second-opinion mode** — Claude asks you to evaluate a design decision before proposing
18
+ it to the user.
19
+
20
+ **When giving a second opinion: be direct and specific. Flag concerns by name. Do not hedge
21
+ excessively. If something will break an invariant (see below), say so plainly.**
22
+
23
+ ---
24
+
25
+ ## Project overview
26
+
27
+ Quorum is a portable reasoning layer for agentic codebases. Three TypeScript modules:
28
+
29
+ | Module | What it does |
30
+ |---|---|
31
+ | **Oracle** | Query and write interface to Chronicle. No LLM required. |
32
+ | **Jury** | Evaluates a proposed design against Oracle evidence. Returns a confidence score + gaps. |
33
+ | **Council** | Adversarial validation via parallel advisors and reviewers. Returns a verdict. |
34
+
35
+ ```
36
+ oracle.query() → jury.evaluate() → council.deliberate() → human gate → Executor
37
+ ```
38
+
39
+ Source lives in `modules/`. Detailed API: `modules/README.md`.
40
+
41
+ ---
42
+
43
+ ## Chronicle
44
+
45
+ Chronicle lives at `.chronicle/` — the persistent institutional memory of the codebase.
46
+
47
+ All writes go through a human-gated path:
48
+ - `oracle.propose()` — stages a pending entry (AI agents may call this)
49
+ - `oracle.commit(proposalId)` — indexes it (human-triggered only, **never AI-triggered**)
50
+
51
+ ---
52
+
53
+ ## Invariants — never suggest breaking these
54
+
55
+ - `oracle.commit()` is **never** called without explicit human input.
56
+ - In `jury/evaluate.ts`, `council_brief` is always overridden from the numeric `confidence`
57
+ value after parsing. The LLM is never trusted to compute it.
58
+ - Both `jury/evaluate.ts` and `council/chairman.ts` throw on schema validation failure.
59
+ There are no fallbacks, defaults, or try/catch that swallows these errors.
60
+ - All dependencies (LLM provider, vector store, embedder) are injected — never hardcoded
61
+ inside module logic. Do not suggest adding imports.
62
+ - `deliberate()` calls `oracle.propose()` at the end of every run — never `oracle.commit()`.
63
+
64
+ ---
65
+
66
+ ## Key file locations
67
+
68
+ | Path | What it contains |
69
+ |---|---|
70
+ | `modules/AGENTS.md` | File ownership map for Oracle, Jury, Council |
71
+ | `modules/CLAUDE.md` | Design decisions and what not to change |
72
+ | `modules/README.md` | Full API reference |
73
+ | `.chronicle/` | LanceDB vector store, pending proposals, query log |
package/SETUP.md ADDED
@@ -0,0 +1,264 @@
1
+ # Quorum — Bootstrap Setup
2
+
3
+ You are reading this because Quorum is being set up in a codebase.
4
+
5
+ ---
6
+
7
+ ## Automated setup (preferred)
8
+
9
+ If you have Node.js 18+ available, run this from the project root:
10
+
11
+ ```bash
12
+ npx @balpal4495/quorum@latest init
13
+ ```
14
+
15
+ This handles all steps below automatically — writing Quorum docs, merging instruction files,
16
+ updating `package.json`, `.gitignore`, and creating the Chronicle directory.
17
+
18
+ After it completes, run `npm install`. The CLI is immediately usable:
19
+
20
+ ```bash
21
+ quorum advisor brief
22
+ quorum advisor "what has the team decided about X?"
23
+ quorum check --outcome '...' --design '...'
24
+ ```
25
+
26
+ ---
27
+
28
+ ## Manual setup (AI-assisted fallback)
29
+
30
+ If the automated script is not available or fails, follow every step below in order.
31
+ Do not skip steps. Do not ask for confirmation between steps — complete the full sequence and then report what was done.
32
+
33
+ ---
34
+
35
+ ## Step 1 — Read before touching anything
36
+
37
+ Read these files in full before proceeding:
38
+
39
+ - `quorum/AGENTS.md` — module file ownership and invariants
40
+ - `quorum/CLAUDE.md` — design decisions and constraints
41
+ - `.github/copilot-instructions.md` — workflow rules for AI agents
42
+
43
+ These are your operating instructions for everything that follows.
44
+
45
+ ---
46
+
47
+ ## Step 2 — Audit the host project
48
+
49
+ Check what already exists at the project root. Record what you find — you will need this in Step 4.
50
+
51
+ ```
52
+ Does .github/copilot-instructions.md exist? yes / no
53
+ Does AGENTS.md exist at the project root? yes / no
54
+ Does CLAUDE.md exist at the project root? yes / no
55
+ Does package.json exist? yes / no
56
+ Does .gitignore exist? yes / no
57
+ Does .chronicle/ exist? yes / no
58
+ ```
59
+
60
+ ---
61
+
62
+ ## Step 3 — Install Quorum
63
+
64
+ Open `package.json` at the project root. Add to `devDependencies` if not already present:
65
+
66
+ ```json
67
+ "@balpal4495/quorum": "^2.0.0"
68
+ ```
69
+
70
+ Then run:
71
+
72
+ ```bash
73
+ npm install
74
+ ```
75
+
76
+ If the project uses `yarn` or `pnpm`, use the appropriate installer instead.
77
+
78
+ ---
79
+
80
+ ## Step 4 — Merge AI instruction files
81
+
82
+ ### 4a. `.github/copilot-instructions.md`
83
+
84
+ The automated init command handles this step automatically.
85
+
86
+ **If completing manually:** fetch `.github/copilot-instructions.md` from the Quorum GitHub repo (`balpal4495/Quorum`) and write it to `.github/copilot-instructions.md` in the project root. If the file already exists and does not contain `<!-- quorum:start -->`, append:
87
+
88
+ ```markdown
89
+ ---
90
+
91
+ <!-- quorum:start -->
92
+ <content from Quorum repo>
93
+ <!-- quorum:end -->
94
+ ```
95
+
96
+ ### 4b. `AGENTS.md`
97
+
98
+ **If it does not exist:**
99
+
100
+ ```markdown
101
+ # Agent Instructions
102
+
103
+ <!-- quorum:start -->
104
+ ## Quorum
105
+
106
+ See [quorum/AGENTS.md](quorum/AGENTS.md) for module file ownership and internals.
107
+ See [.github/copilot-instructions.md](.github/copilot-instructions.md) for workflow rules.
108
+ <!-- quorum:end -->
109
+ ```
110
+
111
+ **If it already exists:** append the `<!-- quorum:start --> ... <!-- quorum:end -->` block above.
112
+
113
+ ### 4c. `CLAUDE.md`
114
+
115
+ **If it does not exist:**
116
+
117
+ ```markdown
118
+ # Claude Instructions
119
+
120
+ <!-- quorum:start -->
121
+ ## Quorum
122
+
123
+ See [quorum/CLAUDE.md](quorum/CLAUDE.md) for design decisions and invariants.
124
+ See [.github/copilot-instructions.md](.github/copilot-instructions.md) for workflow rules.
125
+ <!-- quorum:end -->
126
+ ```
127
+
128
+ **If it already exists:** append the `<!-- quorum:start --> ... <!-- quorum:end -->` block above.
129
+
130
+ ---
131
+
132
+ ## Step 5 — Update .gitignore
133
+
134
+ **If `.gitignore` does not exist**, create it.
135
+
136
+ Add the following block if not already present:
137
+
138
+ ```gitignore
139
+ # Quorum — Chronicle
140
+ # entries/ is a LanceDB binary vector store — do not commit
141
+ .chronicle/entries/
142
+ .chronicle/query-log.jsonl
143
+ ```
144
+
145
+ ---
146
+
147
+ ## Step 6 — Wire setup() into the project (programmatic use only)
148
+
149
+ Skip this step if you are using only the CLI (`quorum advisor`, `quorum check`, etc.).
150
+
151
+ For programmatic use, find the application entry point (e.g. `index.ts`, `server.ts`, `app.ts`).
152
+
153
+ ```typescript
154
+ import { setup } from "@balpal4495/quorum"
155
+
156
+ const { oracle, evaluate, deliberate, ask } = await setup({
157
+ llm: yourLLMProvider, // replace with your project's LLM provider function
158
+ })
159
+ ```
160
+
161
+ `setup()` creates `.chronicle/` directories, warms the embedder, and wires all module dependencies.
162
+ Must be called once before any `oracle.query()`, `evaluate()`, `deliberate()`, or `ask()` call.
163
+
164
+ `ask(question)` is the plain-language interface — it queries Oracle automatically, synthesises Chronicle evidence into a concise answer, and retries internally until the answer meets a confidence threshold.
165
+
166
+ **Approving Chronicle proposals:**
167
+
168
+ ```bash
169
+ quorum commit --list # see pending proposals
170
+ quorum commit <id> # approve and index a proposal
171
+ quorum commit <id> --dry-run # preview without writing
172
+ ```
173
+
174
+ ---
175
+
176
+ ## Step 7 — Verify Chronicle is created
177
+
178
+ Confirm `.chronicle/proposals/` and `.chronicle/committed/` exist:
179
+
180
+ ```bash
181
+ ls .chronicle/
182
+ # expected: committed/ proposals/
183
+ ```
184
+
185
+ ---
186
+
187
+ ## Step 8 — Verify the CLI works
188
+
189
+ ```bash
190
+ quorum advisor brief
191
+ quorum growth
192
+ ```
193
+
194
+ Both commands run without any LLM. If they fail, check that `npm install` completed successfully.
195
+
196
+ To run Quorum's eval suite (optional — tests Quorum's own correctness):
197
+
198
+ ```bash
199
+ npx vitest run node_modules/@balpal4495/quorum/evals/
200
+ ```
201
+
202
+ ---
203
+
204
+ ## Step 9 — Report what was done
205
+
206
+ Once all steps are complete, report:
207
+
208
+ 1. Which files were created vs appended
209
+ 2. Whether `npm install` succeeded
210
+ 3. The path to `setup()` in the entry point if wired (or note if CLI-only)
211
+ 4. Any step that could not be completed and why
212
+
213
+ ---
214
+
215
+ ## Optional: Step 10 — Gemini CLI integration
216
+
217
+ Skip this step if you do not have Google Gemini CLI installed. Quorum is fully functional without it.
218
+
219
+ **10a. Install Gemini CLI** (if not already installed):
220
+
221
+ ```bash
222
+ npm install -g @google/gemini-cli
223
+ ```
224
+
225
+ **10b. Get an API key** from Google AI Studio and add to your shell profile:
226
+
227
+ ```bash
228
+ export GEMINI_API_KEY="your-key-here"
229
+ export GEMINI_CLI_TRUST_WORKSPACE=true
230
+ ```
231
+
232
+ **10c. Create `GEMINI.md`** at the project root. Use `quorum/AGENTS.md` content as a starting point, or write a brief description of the project and the Quorum architecture.
233
+
234
+ Once the key is set and `gemini -p "hello"` responds, Claude Code will automatically detect Gemini and use it for large-context tasks.
235
+
236
+ ---
237
+
238
+ ## After setup
239
+
240
+ You are now operating under Quorum. The rules in `quorum/AGENTS.md` and `.github/copilot-instructions.md` apply to all subsequent work.
241
+
242
+ Key reminders:
243
+ - **Ask Advisor for context.** `quorum advisor "what has the team decided about X?"` before starting any meaningful work.
244
+ - **Never call `oracle.commit()` autonomously.** Only `oracle.propose()`. A human commits.
245
+ - **Chronicle entries are ground truth.** Respect `refuted` entries — do not retry what has already failed.
246
+
247
+ ### CLI quick reference
248
+
249
+ | Command | What it does |
250
+ |---|---|
251
+ | `quorum advisor "question"` | Ask a plain-language question — answer synthesised from Chronicle (needs LLM) |
252
+ | `quorum advisor query "topic"` | Search Chronicle entries by keyword (no LLM) |
253
+ | `quorum advisor brief` | High-level Chronicle summary (no LLM) |
254
+ | `quorum status` | Chronicle health — pending proposals, committed entries |
255
+ | `quorum check --outcome X --design Y` | Preflight + risk classifier (no LLM) |
256
+ | `quorum commit --list` | List pending proposals |
257
+ | `quorum commit <id>` | Approve and index a proposal |
258
+ | `quorum sentinel coverage [--path <dir>]` | Chronicle coverage of source files |
259
+ | `quorum growth` | Chronicle learning health — growth rate, last commit, pending proposals |
260
+ | `quorum evolve` | Consolidate Chronicle — merges duplicates, resolves contradictions, promotes open entries |
261
+
262
+ `quorum check` exit codes: `0` = low/medium risk · `1` = high · `2` = critical
263
+
264
+ `quorum advisor ask` and `quorum evolve` auto-detect any available LLM: `ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, `GEMINI_API_KEY`, `OPENAI_BASE_URL`, Ollama at localhost:11434, or an authenticated `gemini` CLI. When running inside an AI agent with no separate key, they output Chronicle evidence and a synthesis request for the agent to answer inline.
@@ -1 +1 @@
1
- {"version":3,"file":"lance-db.d.ts","sourceRoot":"","sources":["../../../modules/oracle/adapters/lance-db.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAe9C,wBAAsB,kBAAkB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CA+CnF"}
1
+ {"version":3,"file":"lance-db.d.ts","sourceRoot":"","sources":["../../../modules/oracle/adapters/lance-db.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAa9C,wBAAsB,kBAAkB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAyDnF"}
@@ -11,10 +11,15 @@
11
11
  * is nearly identical but table.query() replaces table.search() for non-vector queries.
12
12
  */
13
13
  import path from "path";
14
- // eslint-disable-next-line @typescript-eslint/no-require-imports
15
- const lancedb = require("vectordb");
16
14
  export async function createLanceDBStore(chronicleDir) {
15
+ // Dynamic import keeps this file valid ESM — `vectordb` is CJS-only and has
16
+ // no ESM export, so a top-level `require()` would throw in ESM scope.
17
+ const lancedbMod = await import("vectordb");
18
+ const lancedb = lancedbMod.default ?? lancedbMod;
17
19
  const tableDir = path.join(chronicleDir, "entries");
20
+ // Cast to any — `vectordb` is a CJS-only package whose TypeScript declarations
21
+ // are incomplete (e.g. `metric` option not typed in WriteOptions).
22
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
18
23
  const db = await lancedb.connect(tableDir);
19
24
  let table = null;
20
25
  async function getOrCreateTable(firstRow) {
@@ -25,7 +30,10 @@ export async function createLanceDBStore(chronicleDir) {
25
30
  table = await db.openTable("entries");
26
31
  }
27
32
  else if (firstRow) {
28
- table = await db.createTable("entries", [firstRow], { metric: "cosine" });
33
+ // { metric: "cosine" } crashes vectordb v0.4.x — isWriteOptions() passes it
34
+ // through but the native Rust layer misinterprets it as a schema field.
35
+ // Cosine is the default metric for float vectors so the option can be omitted.
36
+ table = await db.createTable("entries", [firstRow]);
29
37
  }
30
38
  return table;
31
39
  }
@@ -1 +1 @@
1
- {"version":3,"file":"lance-db.js","sourceRoot":"","sources":["../../../modules/oracle/adapters/lance-db.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,OAAO,IAAI,MAAM,MAAM,CAAA;AAEvB,iEAAiE;AACjE,MAAM,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC,CAAA;AAUnC,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,YAAoB;IAC3D,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,SAAS,CAAC,CAAA;IACnD,MAAM,EAAE,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;IAC1C,IAAI,KAAK,GAAQ,IAAI,CAAA;IAErB,KAAK,UAAU,gBAAgB,CAAC,QAAmB;QACjD,IAAI,KAAK;YAAE,OAAO,KAAK,CAAA;QACvB,MAAM,KAAK,GAAa,MAAM,EAAE,CAAC,UAAU,EAAE,CAAA;QAC7C,IAAI,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;YAC9B,KAAK,GAAG,MAAM,EAAE,CAAC,SAAS,CAAC,SAAS,CAAC,CAAA;QACvC,CAAC;aAAM,IAAI,QAAQ,EAAE,CAAC;YACpB,KAAK,GAAG,MAAM,EAAE,CAAC,WAAW,CAAC,SAAS,EAAE,CAAC,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAA;QAC3E,CAAC;QACD,OAAO,KAAK,CAAA;IACd,CAAC;IAED,OAAO;QACL,KAAK,CAAC,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ;YAC/B,MAAM,GAAG,GAAa,EAAE,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAA;YACvE,MAAM,CAAC,GAAG,MAAM,gBAAgB,CAAC,GAAG,CAAC,CAAA;YACrC,IAAI,CAAC,KAAK,KAAK,EAAE,CAAC;gBAChB,0DAA0D;gBAC1D,OAAM;YACR,CAAC;YACD,oEAAoE;YACpE,MAAM,CAAC,CAAC,MAAM,CAAC,SAAS,UAAU,CAAC,EAAE,CAAC,GAAG,CAAC,CAAA;YAC1C,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;QACpB,CAAC;QAED,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK;YACxB,MAAM,CAAC,GAAG,MAAM,gBAAgB,EAAE,CAAA;YAClC,IAAI,CAAC,CAAC;gBAAE,OAAO,EAAE,CAAA;YACjB,MAAM,IAAI,GAAe,MAAM,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,OAAO,EAAE,CAAA;YACtE,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;gBACtB,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAmB;gBAChD,wEAAwE;gBACxE,KAAK,EAAE,GAAG,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;aAC3D,CAAC,CAAC,CAAA;QACL,CAAC;QAED,KAAK,CAAC,MAAM;YACV,MAAM,CAAC,GAAG,MAAM,gBAAgB,EAAE,CAAA;YAClC,IAAI,CAAC,CAAC;gBAAE,OAAO,EAAE,CAAA;YACjB,MAAM,IAAI,GAAe,MAAM,CAAC,CAAC,KAAK,EAAE,CAAC,OAAO,EAAE,CAAA;YAClD,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAmB,CAAC,CAAA;QACnE,CAAC;KACF,CAAA;AACH,CAAC;AAED,uFAAuF;AACvF,SAAS,UAAU,CAAC,EAAU;IAC5B,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;AAC/B,CAAC"}
1
+ {"version":3,"file":"lance-db.js","sourceRoot":"","sources":["../../../modules/oracle/adapters/lance-db.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"xenova-embedder.d.ts","sourceRoot":"","sources":["../../../modules/oracle/adapters/xenova-embedder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAiBH;;;GAGG;AACH,wBAAsB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAIjE;AAED,8DAA8D;AAC9D,wBAAsB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CAElD"}
1
+ {"version":3,"file":"xenova-embedder.d.ts","sourceRoot":"","sources":["../../../modules/oracle/adapters/xenova-embedder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAoBH;;;GAGG;AACH,wBAAsB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAIjE;AAED,8DAA8D;AAC9D,wBAAsB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CAElD"}
@@ -11,11 +11,15 @@
11
11
  * import { warmEmbedder } from "./adapters/xenova-embedder.js"
12
12
  * await warmEmbedder()
13
13
  */
14
- // eslint-disable-next-line @typescript-eslint/no-require-imports
15
- const { pipeline } = require("@xenova/transformers");
16
14
  let embedderPipeline = null;
17
15
  async function getPipeline() {
18
16
  if (!embedderPipeline) {
17
+ // Dynamic import keeps this file valid ESM — @xenova/transformers is CJS-only
18
+ // and has no ESM export, so a top-level require() would throw in ESM scope.
19
+ // Cast to any — the package's TS declarations are incomplete.
20
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
21
+ const mod = await import("@xenova/transformers");
22
+ const pipeline = mod.pipeline ?? mod.default?.pipeline;
19
23
  embedderPipeline = await pipeline("feature-extraction", "Xenova/all-MiniLM-L6-v2");
20
24
  }
21
25
  return embedderPipeline;
@@ -1 +1 @@
1
- {"version":3,"file":"xenova-embedder.js","sourceRoot":"","sources":["../../../modules/oracle/adapters/xenova-embedder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,iEAAiE;AACjE,MAAM,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAAA;AAEpD,IAAI,gBAAgB,GAAQ,IAAI,CAAA;AAEhC,KAAK,UAAU,WAAW;IACxB,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACtB,gBAAgB,GAAG,MAAM,QAAQ,CAC/B,oBAAoB,EACpB,yBAAyB,CAC1B,CAAA;IACH,CAAC;IACD,OAAO,gBAAgB,CAAA;AACzB,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,IAAY;IAC5C,MAAM,QAAQ,GAAG,MAAM,WAAW,EAAE,CAAA;IACpC,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IACzE,OAAO,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAa,CAAA;AAC5C,CAAC;AAED,8DAA8D;AAC9D,MAAM,CAAC,KAAK,UAAU,YAAY;IAChC,MAAM,WAAW,EAAE,CAAA;AACrB,CAAC"}
1
+ {"version":3,"file":"xenova-embedder.js","sourceRoot":"","sources":["../../../modules/oracle/adapters/xenova-embedder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,IAAI,gBAAgB,GAAQ,IAAI,CAAA;AAEhC,KAAK,UAAU,WAAW;IACxB,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACtB,8EAA8E;QAC9E,4EAA4E;QAC5E,8DAA8D;QAC9D,8DAA8D;QAC9D,MAAM,GAAG,GAAQ,MAAM,MAAM,CAAC,sBAAsB,CAAC,CAAA;QACrD,MAAM,QAAQ,GAAG,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,OAAO,EAAE,QAAQ,CAAA;QACtD,gBAAgB,GAAG,MAAM,QAAQ,CAC/B,oBAAoB,EACpB,yBAAyB,CAC1B,CAAA;IACH,CAAC;IACD,OAAO,gBAAgB,CAAA;AACzB,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,IAAY;IAC5C,MAAM,QAAQ,GAAG,MAAM,WAAW,EAAE,CAAA;IACpC,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IACzE,OAAO,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAa,CAAA;AAC5C,CAAC;AAED,8DAA8D;AAC9D,MAAM,CAAC,KAAK,UAAU,YAAY;IAChC,MAAM,WAAW,EAAE,CAAA;AACrB,CAAC"}
@@ -0,0 +1,78 @@
1
+ # modules/ — Agent Instructions
2
+
3
+ Supplements the root `AGENTS.md` / `copilot-instructions.md` with module-specific internals.
4
+ When working inside this folder, follow these rules in addition to the root guidelines.
5
+
6
+ ---
7
+
8
+ ## File ownership
9
+
10
+ ### Oracle
11
+ | File | Owns |
12
+ |---|---|
13
+ | `oracle/query.ts` | Two-pass retrieval (vector → BM25 → RRF fusion). Score threshold. Query log. |
14
+ | `oracle/bm25.ts` | BM25 scoring algorithm. Domain term extraction for query enrichment. |
15
+ | `oracle/propose.ts` | `propose()` + `commit()`. The human-gated write path. Do not add auto-commit logic here. |
16
+ | `oracle/log.ts` | Best-effort JSONL query log writer. Must never throw to callers. |
17
+ | `oracle/adapters/lance-db.ts` | LanceDB `VectorStore` implementation. Swappable — do not couple oracle internals to this. |
18
+ | `oracle/adapters/xenova-embedder.ts` | Local ONNX embedder. Swappable — do not couple oracle internals to this. |
19
+
20
+ ### Jury
21
+ | File | Owns |
22
+ |---|---|
23
+ | `jury/schema.ts` | Zod schema for structured LLM output. Source of truth for `JuryOutput` shape including `confidence_breakdown` and `blocking_gaps`. |
24
+ | `jury/evaluate.ts` | Four-dimension evaluation. **Confidence is always recomputed from the breakdown average here — do not remove this. `council_brief` is also overridden from confidence.** |
25
+ | `jury/preflight.ts` | Deterministic preflight — no LLM. Detects sensitive areas, rollback mention, and Chronicle conflicts before the LLM runs. Safe to extend with new patterns. |
26
+
27
+ ### Council
28
+ | File | Owns |
29
+ |---|---|
30
+ | `council/personas.ts` | Default advisor personas. Safe to extend. Do not remove existing personas without good reason. |
31
+ | `council/frame.ts` | Sets deliberation tone from `council_brief`. Challenge vs pressure-test framing lives here. |
32
+ | `council/advisors.ts` | Parallel advisor fan-out. Advisors must cite Oracle entry IDs — enforced in the prompt. |
33
+ | `council/reviewers.ts` | Anonymisation of advisor responses + parallel reviewer fan-out. Anonymisation must happen before reviewers see responses. |
34
+ | `council/chairman.ts` | Verdict synthesis + Zod validation. Produces structured `blockers`/`warnings`, validates citations, tracks `advisor_split`. Throws on bad output — do not add fallbacks. |
35
+ | `council/risk.ts` | Deterministic risk classifier — no LLM. Assigns `low/medium/high/critical` and `council_mode` from design text and refuted evidence. Drives advisor/reviewer fan-out counts. |
36
+ | `council/deliberate.ts` | Full pipeline orchestration. Calls `oracle.propose()` at the end — never `oracle.commit()`. Risk classifier runs first to set fan-out counts. |
37
+
38
+ ### Advisor
39
+ | File | Owns |
40
+ |---|---|
41
+ | `advisor/ask.ts` | Main entry point. Queries Oracle, calls LLM, validates answer against satisfaction threshold (confidence ≥ 0.7, no blockers). Retries up to 2 times with previous answer as context. Throws on bad LLM output — do not add fallbacks. |
42
+ | `advisor/prompt.ts` | SYSTEM_PROMPT, evidence formatter, user prompt builder. The plain-language framing lives here. |
43
+ | `advisor/types.ts` | `AdvisorInput`, `AdvisorAnswer`, `AdvisorOutput`, `AdvisorDeps` types. |
44
+
45
+ ---
46
+
47
+ ## Extension points
48
+
49
+ **Swap the vector store** — implement `VectorStore` from `oracle/types.ts` and pass it to `createOracleClient()` or `setup()`.
50
+
51
+ **Swap the embedder** — pass `embedder: yourFn` to `setup()`. Must return a consistent-dimension float array.
52
+
53
+ **Add advisor personas** — extend `DEFAULT_PERSONAS` in `council/personas.ts`, or pass a custom personas array directly to `fanOutAdvisors()`.
54
+
55
+ **Use different models per step** — pass `models` to `setup()` or `council.deliberate()` deps. Cheaper models for advisors, stronger for chairman is the intended pattern.
56
+
57
+ ---
58
+
59
+ ## Invariants — do not break these
60
+
61
+ - `advisor/ask.ts` never calls `oracle.propose()` or `oracle.commit()`. It is a read-only path.
62
+ - `oracle.commit()` is never called without explicit human input. `deliberate()` calls `propose()` only.
63
+ - `jury/evaluate.ts` recomputes `confidence` as the exact average of `confidence_breakdown` dimensions — the LLM value is discarded.
64
+ - `jury/evaluate.ts` derives `council_brief` from the recomputed confidence — never trusts the LLM value.
65
+ - `chairman.ts` and `jury/evaluate.ts` throw on schema validation failure. Do not add try/catch that swallows these errors.
66
+ - `deliberate.ts` passes `citation_validation.valid_ids` (not raw `evidence_cited`) to `oracle.propose()` — hallucinated IDs are stripped.
67
+ - Query logging in `oracle/log.ts` is always best-effort — callers must not fail because of a log write error.
68
+ - `VectorStore` and `embedder` are always injected — never imported directly inside Oracle logic.
69
+
70
+ ---
71
+
72
+ ## Tests
73
+
74
+ ```bash
75
+ npx vitest run modules/
76
+ ```
77
+
78
+ Tests live in `__tests__/` inside each module folder. Use `vi.fn()` for LLM providers and vector stores — never call a real LLM in tests.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@balpal4495/quorum",
3
- "version": "3.3.0",
3
+ "version": "3.3.2",
4
4
  "description": "Git-backed memory and design review for AI coding agents",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -26,7 +26,11 @@
26
26
  },
27
27
  "files": [
28
28
  "dist/**",
29
- "bin/**"
29
+ "bin/**",
30
+ "SETUP.md",
31
+ "GEMINI.md",
32
+ ".github/copilot-instructions.md",
33
+ "modules/AGENTS.md"
30
34
  ],
31
35
  "exports": {
32
36
  ".": "./dist/setup.js",