@balpal4495/quorum 0.1.9 → 0.1.10
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/README.md +108 -237
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,327 +1,198 @@
|
|
|
1
1
|
# Quorum
|
|
2
2
|
|
|
3
|
-
**Quorum gives AI
|
|
3
|
+
**Quorum gives your AI coding assistant memory and judgment.**
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
When Claude Code, Copilot, or Cursor works in your codebase, it forgets everything between sessions. It retries approaches that already failed. It contradicts decisions made last week. It has no idea what the team has already learned.
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
npx @balpal4495/quorum@latest init
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
That's it. Quorum copies itself into your project, merges instruction files for your AI, and creates the knowledge store directory. Run `npm install` and you're ready.
|
|
7
|
+
Quorum fixes this. It installs a persistent knowledge store into your project and gives your AI a structured workflow for querying it before proposing solutions, validating designs before acting, and writing new knowledge back — with you approving every write.
|
|
12
8
|
|
|
13
9
|
---
|
|
14
10
|
|
|
15
|
-
##
|
|
11
|
+
## Get started in one command
|
|
12
|
+
|
|
13
|
+
Run this from your project root:
|
|
16
14
|
|
|
17
|
-
|
|
15
|
+
```bash
|
|
16
|
+
npx @balpal4495/quorum@latest init
|
|
17
|
+
```
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
Then run `npm install`.
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|---|---|
|
|
23
|
-
| **Oracle** | Stores and retrieves project knowledge — decisions, investigations, outcomes |
|
|
24
|
-
| **Jury** | Scores a proposed design against that knowledge — gives you confidence before acting |
|
|
25
|
-
| **Council** | A panel of advisors challenges the design and a Chairman gives a final verdict |
|
|
26
|
-
| **Sentinel** | Shows you which parts of the codebase the AI knows nothing about — and flags stale knowledge |
|
|
21
|
+
That's the whole setup. Quorum copies its modules into `quorum/`, merges instruction files for your AI (`CLAUDE.md`, `AGENTS.md`, `.github/copilot-instructions.md`), and creates the Chronicle knowledge store at `.chronicle/`.
|
|
27
22
|
|
|
28
23
|
---
|
|
29
24
|
|
|
30
|
-
##
|
|
25
|
+
## Then just talk to your AI
|
|
31
26
|
|
|
32
|
-
|
|
27
|
+
Once initialized, open your AI in agent mode and tell it:
|
|
33
28
|
|
|
34
|
-
|
|
35
|
-
oracle.query() → jury.evaluate() → council.deliberate() → human gate → Executor
|
|
36
|
-
```
|
|
29
|
+
> "Follow quorum/SETUP.md"
|
|
37
30
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
sequenceDiagram
|
|
46
|
-
participant Agent as AI Agent
|
|
47
|
-
participant Oracle
|
|
48
|
-
participant Jury
|
|
49
|
-
participant Council
|
|
50
|
-
participant Human
|
|
51
|
-
participant Chronicle
|
|
52
|
-
|
|
53
|
-
Agent->>Oracle: query(text)
|
|
54
|
-
Oracle->>Chronicle: vector + BM25 search
|
|
55
|
-
Chronicle-->>Agent: ranked evidence
|
|
56
|
-
|
|
57
|
-
Agent->>Jury: evaluate(design, evidence)
|
|
58
|
-
Jury-->>Agent: confidence score + gaps
|
|
59
|
-
|
|
60
|
-
Agent->>Council: deliberate(design, evidence, jury_output)
|
|
61
|
-
Council-->>Agent: verdict + proposal
|
|
62
|
-
|
|
63
|
-
alt Council satisfied
|
|
64
|
-
Agent->>Human: surface verdict for approval
|
|
65
|
-
Human->>Oracle: commit(proposalId)
|
|
66
|
-
Oracle->>Chronicle: index entry
|
|
67
|
-
else not satisfied
|
|
68
|
-
Note over Agent: revise and retry
|
|
69
|
-
end
|
|
70
|
-
```
|
|
31
|
+
Your AI reads the instruction files, wires the modules into your project's entry point, runs the tests, and reports what it did. From that point it operates under Quorum — querying Chronicle before every proposal, running designs through Jury and Council, and staging entries for your approval.
|
|
32
|
+
|
|
33
|
+
**Works with:**
|
|
34
|
+
- Claude Code (`claude` CLI or VS Code extension)
|
|
35
|
+
- GitHub Copilot (agent mode)
|
|
36
|
+
- Cursor
|
|
37
|
+
- Any other AI that can read files and run terminal commands
|
|
71
38
|
|
|
72
39
|
---
|
|
73
40
|
|
|
74
|
-
##
|
|
41
|
+
## What changes after setup
|
|
75
42
|
|
|
76
|
-
###
|
|
43
|
+
### Your AI now has a memory
|
|
77
44
|
|
|
78
|
-
|
|
45
|
+
Before proposing anything, your AI queries Chronicle — the project's knowledge store. If a similar approach was tried and rejected, it knows. If a design decision was made last month, it knows.
|
|
79
46
|
|
|
80
|
-
|
|
81
|
-
[abc-123] Tried symmetric JWT (HS256) in March. Rejected — no way to rotate keys
|
|
82
|
-
without invalidating all active sessions. Use RS256 with short-lived tokens.
|
|
83
|
-
confidence: 0.91 · status: committed
|
|
84
|
-
```
|
|
47
|
+
> *"I queried Chronicle before proposing the Redis session approach. Entry `[abc-123]` shows we rejected this in March — key rotation wasn't viable. I'm proposing JWT with RS256 instead."*
|
|
85
48
|
|
|
86
|
-
|
|
49
|
+
### Your AI validates designs before acting
|
|
87
50
|
|
|
88
|
-
|
|
51
|
+
Every proposal goes through Jury (confidence scoring against evidence) and Council (adversarial panel review) before it reaches you. Low-confidence or contested ideas get challenged internally first.
|
|
89
52
|
|
|
90
|
-
|
|
53
|
+
> *"Jury scored this 0.41 — gaps in lock strategy and rollback plan. Council flagged the same issue. I've revised the migration plan to use a shadow column approach before bringing it to you."*
|
|
91
54
|
|
|
92
|
-
|
|
55
|
+
### You approve what gets remembered
|
|
56
|
+
|
|
57
|
+
When a decision is made, your AI stages a Chronicle entry using `oracle.propose()`. You approve it with `oracle.commit(proposalId)`. Nothing is indexed without your explicit sign-off.
|
|
93
58
|
|
|
94
|
-
```
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
design: "ALTER TABLE, backfill with default false, then add constraint",
|
|
100
|
-
evidence,
|
|
101
|
-
})
|
|
102
|
-
// jury.confidence: 0.41 — gaps: ["no lock strategy", "no rollback plan"]
|
|
103
|
-
|
|
104
|
-
const verdict = await deliberate({
|
|
105
|
-
outcome: "Add NOT NULL column users.verified",
|
|
106
|
-
design: "ALTER TABLE, backfill with default false, then add constraint",
|
|
107
|
-
evidence,
|
|
108
|
-
jury_output: jury,
|
|
109
|
-
})
|
|
110
|
-
// verdict.satisfied: false
|
|
111
|
-
// verdict.verdict: "No lock strategy specified. On a table this size, a naive ALTER TABLE
|
|
112
|
-
// will take an exclusive lock for minutes. Use a shadow column pattern
|
|
113
|
-
// or pg_repack."
|
|
59
|
+
```
|
|
60
|
+
.chronicle/
|
|
61
|
+
proposals/ ← AI-staged entries waiting for your approval
|
|
62
|
+
committed/ ← approved entries, indexed and searchable
|
|
63
|
+
SUMMARY.md ← auto-generated weekly context for your AI to read
|
|
114
64
|
```
|
|
115
65
|
|
|
116
|
-
|
|
66
|
+
Commit `.chronicle/committed/` to git. Future sessions — and your teammates' sessions — start with that context.
|
|
117
67
|
|
|
118
68
|
---
|
|
119
69
|
|
|
120
|
-
|
|
70
|
+
## Real examples
|
|
121
71
|
|
|
122
|
-
|
|
72
|
+
### An agent that remembers a past failure
|
|
73
|
+
|
|
74
|
+
Your AI is about to propose symmetric JWT signing. Oracle returns:
|
|
123
75
|
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
76
|
+
```
|
|
77
|
+
[abc-123] Tried HS256 JWT in March. Rejected — no way to rotate keys without
|
|
78
|
+
invalidating all active sessions. Decision: RS256 with short-lived tokens.
|
|
79
|
+
status: committed · confidence: 0.91
|
|
128
80
|
```
|
|
129
81
|
|
|
130
|
-
|
|
82
|
+
Jury flags it as a direct conflict. The agent revises before Council even sees it.
|
|
131
83
|
|
|
132
84
|
---
|
|
133
85
|
|
|
134
|
-
|
|
86
|
+
### Onboarding a new session to an established project
|
|
135
87
|
|
|
136
|
-
|
|
137
|
-
import { setup } from "./quorum/modules/setup"
|
|
88
|
+
Day one of a new Claude Code session. Before touching anything:
|
|
138
89
|
|
|
139
|
-
const { oracle, evaluate, deliberate } = await setup({
|
|
140
|
-
llm: myLLMProvider, // any function that calls your LLM — see wiring below
|
|
141
|
-
})
|
|
142
|
-
|
|
143
|
-
// Query what Chronicle knows
|
|
144
|
-
const evidence = await oracle.query("authentication patterns in this codebase")
|
|
145
|
-
|
|
146
|
-
// Evaluate a proposed design
|
|
147
|
-
const jury = await evaluate({
|
|
148
|
-
outcome: "Add OAuth2 login via GitHub",
|
|
149
|
-
design: "Use passport-github2, store sessions in Redis, 1-hour TTL",
|
|
150
|
-
evidence,
|
|
151
|
-
})
|
|
152
|
-
|
|
153
|
-
// Get a Council verdict
|
|
154
|
-
const verdict = await deliberate({
|
|
155
|
-
outcome: "Add OAuth2 login via GitHub",
|
|
156
|
-
design: "Use passport-github2, store sessions in Redis, 1-hour TTL",
|
|
157
|
-
evidence,
|
|
158
|
-
jury_output: jury,
|
|
159
|
-
})
|
|
160
|
-
|
|
161
|
-
if (verdict.satisfied) {
|
|
162
|
-
// → surface verdict.proposal to a human for approval
|
|
163
|
-
// → human calls oracle.commit(proposalId) to index it
|
|
164
|
-
// → Executor proceeds
|
|
165
|
-
} else {
|
|
166
|
-
// verdict.verdict contains the specific objection
|
|
167
|
-
// verdict.recommendation is "redesign" or "investigate-more"
|
|
168
|
-
}
|
|
169
90
|
```
|
|
91
|
+
> query Chronicle for: authentication, session handling, token strategy
|
|
170
92
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
```typescript
|
|
178
|
-
import type { LLMProvider } from "./quorum/modules/shared/types"
|
|
93
|
+
6 entries found:
|
|
94
|
+
- HS256 rejected (key rotation problem) → use RS256
|
|
95
|
+
- Redis sessions tried and removed (memory overhead at scale)
|
|
96
|
+
- Current approach: RS256 JWT, 15-min expiry, refresh rotation in httpOnly cookies
|
|
97
|
+
- Upcoming: OAuth migration planned for Q3
|
|
179
98
|
```
|
|
180
99
|
|
|
181
|
-
|
|
182
|
-
// Anthropic
|
|
183
|
-
const llm: LLMProvider = async (messages, model = "claude-3-5-sonnet-20241022") => {
|
|
184
|
-
const system = messages.find(m => m.role === "system")?.content ?? ""
|
|
185
|
-
const user = messages.filter(m => m.role !== "system")
|
|
186
|
-
const res = await anthropic.messages.create({ model, system, messages: user, max_tokens: 2048 })
|
|
187
|
-
return res.content[0].type === "text" ? res.content[0].text : ""
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
// OpenAI
|
|
191
|
-
const llm: LLMProvider = async (messages, model = "gpt-4o") => {
|
|
192
|
-
const res = await openai.chat.completions.create({ model, messages })
|
|
193
|
-
return res.choices[0].message.content ?? ""
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
// Per-step model overrides (optional)
|
|
197
|
-
const { oracle, evaluate, deliberate } = await setup({
|
|
198
|
-
llm,
|
|
199
|
-
models: {
|
|
200
|
-
jury: "gpt-4o-mini",
|
|
201
|
-
council: {
|
|
202
|
-
frame: "gpt-4o-mini",
|
|
203
|
-
advisors: "gpt-4o-mini",
|
|
204
|
-
reviewers: "gpt-4o",
|
|
205
|
-
chairman: "gpt-4o",
|
|
206
|
-
},
|
|
207
|
-
},
|
|
208
|
-
})
|
|
209
|
-
```
|
|
210
|
-
|
|
211
|
-
Oracle requires no LLM — only Jury, Council, and Sentinel drift checks need one.
|
|
100
|
+
The AI works with full project context from the first message — no archaeology through git history.
|
|
212
101
|
|
|
213
102
|
---
|
|
214
103
|
|
|
215
|
-
|
|
104
|
+
### Validating a risky database change
|
|
216
105
|
|
|
217
|
-
|
|
106
|
+
An agent proposes adding a `NOT NULL` column to a 50M-row table. Jury returns:
|
|
218
107
|
|
|
219
108
|
```
|
|
220
|
-
.
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
SUMMARY.md ← auto-generated weekly context, rebuilt on every commit
|
|
109
|
+
confidence: 0.41
|
|
110
|
+
gaps: ["no lock strategy documented", "no rollback plan"]
|
|
111
|
+
council_brief: challenge
|
|
224
112
|
```
|
|
225
113
|
|
|
226
|
-
|
|
114
|
+
Council's Chairman gives a verdict:
|
|
227
115
|
|
|
228
116
|
```
|
|
229
|
-
|
|
230
|
-
|
|
117
|
+
satisfied: false
|
|
118
|
+
verdict: "On a table this size, a naive ALTER TABLE takes an exclusive lock for minutes.
|
|
119
|
+
Specify a shadow column pattern or pg_repack. No rollback plan documented."
|
|
231
120
|
```
|
|
232
121
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
There are no auto-commits. Ever.
|
|
122
|
+
The agent revises the plan. You approve the Chronicle entry once it's solid. The reasoning is on record for the next time someone touches that table.
|
|
236
123
|
|
|
237
124
|
---
|
|
238
125
|
|
|
239
|
-
##
|
|
126
|
+
## What's inside
|
|
240
127
|
|
|
241
|
-
|
|
128
|
+
Four portable TypeScript modules installed into `quorum/modules/`:
|
|
242
129
|
|
|
243
|
-
|
|
130
|
+
| Module | What it does |
|
|
131
|
+
|---|---|
|
|
132
|
+
| **Oracle** | Query and write interface to Chronicle. No LLM required. |
|
|
133
|
+
| **Jury** | Evaluates a proposed design against Chronicle evidence. Returns a confidence score. |
|
|
134
|
+
| **Council** | A panel of advisors challenges the design independently, reviewers critique anonymously, a Chairman gives a final verdict. |
|
|
135
|
+
| **Sentinel** | Shows which files the AI knows nothing about, flags stale knowledge, and posts a coverage map on every PR. |
|
|
244
136
|
|
|
245
|
-
|
|
246
|
-
import { coverage } from "./quorum/modules/sentinel"
|
|
137
|
+
The modules live in your repo — readable by any AI working in the codebase. Nothing is hidden in `node_modules`.
|
|
247
138
|
|
|
248
|
-
|
|
249
|
-
// report.percentage — 34%
|
|
250
|
-
// report.uncoveredFiles — ["src/auth/session.ts", "src/payments/stripe.ts", ...]
|
|
251
|
-
```
|
|
139
|
+
---
|
|
252
140
|
|
|
253
|
-
|
|
141
|
+
## Sentinel — coverage and drift
|
|
254
142
|
|
|
255
|
-
|
|
256
|
-
import { detectDrift } from "./quorum/modules/sentinel"
|
|
143
|
+
Sentinel surfaces two things Chronicle can't tell you about itself.
|
|
257
144
|
|
|
258
|
-
|
|
259
|
-
// report.flags — entries where the key_insight may no longer match the code
|
|
260
|
-
```
|
|
145
|
+
**Coverage** — which parts of your codebase has the AI never documented?
|
|
261
146
|
|
|
262
|
-
|
|
147
|
+
**Drift** — do existing Chronicle entries still accurately describe the code, or have they gone stale?
|
|
263
148
|
|
|
264
|
-
|
|
265
|
-
import { describe } from "vitest"
|
|
266
|
-
import { sentinelAssertions } from "./quorum/modules/sentinel"
|
|
267
|
-
|
|
268
|
-
describe("sentinel", () => {
|
|
269
|
-
sentinelAssertions({
|
|
270
|
-
chronicleDir: ".chronicle",
|
|
271
|
-
codebasePath: "src",
|
|
272
|
-
llm: myLLMProvider, // omit to skip drift tests
|
|
273
|
-
minCoveragePercent: 50, // 0 = advisory only (default — safe for new projects)
|
|
274
|
-
}).forEach(a => a())
|
|
275
|
-
})
|
|
276
|
-
```
|
|
149
|
+
Add `sentinel-pr.yml` (included in `quorum/`) to your GitHub Actions and every PR gets a comment showing a full-project coverage table and a colour-coded heatmap. Changed modules are highlighted. Reviewers see exactly where knowledge is solid and where it goes dark.
|
|
277
150
|
|
|
278
|
-
|
|
151
|
+
---
|
|
279
152
|
|
|
280
|
-
|
|
153
|
+
## For custom agent pipelines
|
|
281
154
|
|
|
282
|
-
|
|
155
|
+
If you're building your own agent workflow programmatically, the modules expose a clean TypeScript API. Wire your LLM provider and call directly:
|
|
283
156
|
|
|
284
|
-
|
|
157
|
+
```typescript
|
|
158
|
+
import { setup } from "./quorum/modules/setup"
|
|
285
159
|
|
|
286
|
-
|
|
287
|
-
|---|---|---|
|
|
288
|
-
| Oracle | No | `oracle.query()` / `oracle.propose()` / `oracle.commit()` |
|
|
289
|
-
| Jury | Yes | `evaluate(input, deps)` |
|
|
290
|
-
| Council | Yes | `deliberate(input, deps)` |
|
|
291
|
-
| Sentinel | Optional | `coverage()` / `detectDrift()` / `sentinelAssertions()` |
|
|
160
|
+
const { oracle, evaluate, deliberate } = await setup({ llm: myLLMProvider })
|
|
292
161
|
|
|
293
|
-
|
|
294
|
-
|
|
162
|
+
const evidence = await oracle.query("authentication patterns")
|
|
163
|
+
const jury = await evaluate({ outcome, design, evidence })
|
|
164
|
+
const verdict = await deliberate({ outcome, design, evidence, jury_output: jury })
|
|
165
|
+
```
|
|
295
166
|
|
|
296
|
-
|
|
167
|
+
The `LLMProvider` type is a simple function — wire OpenAI, Anthropic, or anything else:
|
|
297
168
|
|
|
298
|
-
|
|
169
|
+
```typescript
|
|
170
|
+
// Anthropic
|
|
171
|
+
const llm = async (messages, model = "claude-3-5-sonnet-20241022") => {
|
|
172
|
+
const res = await anthropic.messages.create({ model, messages, max_tokens: 2048 })
|
|
173
|
+
return res.content[0].type === "text" ? res.content[0].text : ""
|
|
174
|
+
}
|
|
299
175
|
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
176
|
+
// OpenAI
|
|
177
|
+
const llm = async (messages, model = "gpt-4o") => {
|
|
178
|
+
const res = await openai.chat.completions.create({ model, messages })
|
|
179
|
+
return res.choices[0].message.content ?? ""
|
|
180
|
+
}
|
|
181
|
+
```
|
|
305
182
|
|
|
306
|
-
|
|
183
|
+
Full API reference: [modules/README.md](modules/README.md)
|
|
307
184
|
|
|
308
185
|
---
|
|
309
186
|
|
|
310
187
|
## Releases
|
|
311
188
|
|
|
312
|
-
Quorum is published
|
|
313
|
-
|
|
314
|
-
```bash
|
|
315
|
-
git tag v0.2.0 && git push origin v0.2.0
|
|
316
|
-
```
|
|
317
|
-
|
|
318
|
-
GitHub Actions publishes to npm automatically via OIDC Trusted Publishing — no stored tokens.
|
|
189
|
+
Quorum is published as `@balpal4495/quorum`. New versions release automatically when a semver tag is pushed — via GitHub Actions and OIDC Trusted Publishing, no stored tokens.
|
|
319
190
|
|
|
320
191
|
---
|
|
321
192
|
|
|
322
193
|
## Docs
|
|
323
194
|
|
|
324
|
-
- [
|
|
325
|
-
- [modules/
|
|
195
|
+
- [SETUP.md](SETUP.md) — full bootstrap sequence (the file you point your AI at)
|
|
196
|
+
- [modules/README.md](modules/README.md) — TypeScript API reference
|
|
197
|
+
- [modules/AGENTS.md](modules/AGENTS.md) — file ownership map
|
|
326
198
|
- [modules/CLAUDE.md](modules/CLAUDE.md) — design decisions and invariants
|
|
327
|
-
- [SETUP.md](SETUP.md) — manual bootstrap sequence (for AI-assisted setup)
|