@balpal4495/quorum 0.1.10 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/README.md +118 -9
  2. package/SETUP.md +6 -0
  3. package/evals/__tests__/eval.test.ts +31 -0
  4. package/evals/cases/auth_hs256_rejected.json +46 -0
  5. package/evals/cases/auth_rs256_valid.json +30 -0
  6. package/evals/cases/cache_missing_lock.json +31 -0
  7. package/evals/cases/db_naive_not_null.json +32 -0
  8. package/evals/cases/logging_pii_leak.json +32 -0
  9. package/evals/cases/migration_with_rollback.json +43 -0
  10. package/evals/cases/no_evidence_novel_design.json +16 -0
  11. package/evals/cases/payment_no_idempotency.json +33 -0
  12. package/evals/cases/redis_session_rejected.json +32 -0
  13. package/evals/cases/safe_refactor.json +17 -0
  14. package/evals/runner.ts +226 -0
  15. package/modules/AGENTS.md +9 -5
  16. package/modules/CLAUDE.md +25 -2
  17. package/modules/README.md +153 -6
  18. package/modules/council/advisors.ts +4 -1
  19. package/modules/council/chairman.ts +86 -15
  20. package/modules/council/deliberate.ts +28 -3
  21. package/modules/council/index.ts +6 -1
  22. package/modules/council/reviewers.ts +2 -1
  23. package/modules/council/risk.ts +89 -0
  24. package/modules/council/types.ts +63 -1
  25. package/modules/jury/evaluate.ts +35 -10
  26. package/modules/jury/index.ts +3 -1
  27. package/modules/jury/preflight.ts +101 -0
  28. package/modules/jury/schema.ts +9 -0
  29. package/modules/jury/types.ts +20 -1
  30. package/modules/oracle/propose.ts +19 -3
  31. package/modules/oracle/query.ts +3 -2
  32. package/modules/oracle/summary.ts +2 -1
  33. package/modules/sentinel/drift.ts +7 -3
  34. package/modules/sentinel/review.ts +2 -1
  35. package/modules/setup.ts +2 -1
  36. package/modules/shared/types.ts +47 -2
  37. package/package.json +2 -2
@@ -1,6 +1,7 @@
1
1
  import { promises as fs } from "fs"
2
2
  import path from "path"
3
3
  import type { ChronicleEntry } from "../shared/types"
4
+ import { entryText } from "../shared/types"
4
5
  import { coverage as runCoverage } from "./coverage"
5
6
 
6
7
  function extractModule(filePath: string): string {
@@ -192,7 +193,7 @@ export async function reviewContext(
192
193
  lines.push(`**${stat.name}/**`)
193
194
  const relevant = allEntries.filter(e => stat.entryIds.includes(e.id))
194
195
  for (const entry of relevant) {
195
- lines.push(`- \`[${entry.id.slice(0, 8)}]\` ${entry.key_insight}`)
196
+ lines.push(`- \`[${entry.id.slice(0, 8)}]\` ${entryText(entry)}`)
196
197
  lines.push(` *${entry.status} — confidence ${entry.confidence.toFixed(2)}*`)
197
198
  }
198
199
  lines.push("")
package/modules/setup.ts CHANGED
@@ -6,6 +6,7 @@ import { createLanceDBStore } from "./oracle/adapters/lance-db"
6
6
  import { evaluate } from "./jury/evaluate"
7
7
  import { deliberate } from "./council/deliberate"
8
8
  import type { LLMProvider, OracleClient } from "./shared/types"
9
+ import { entryText } from "./shared/types"
9
10
  import type { JuryInput, JuryOutput, JuryDeps } from "./jury/types"
10
11
  import type { CouncilInput, CouncilOutput, CouncilDeps, CouncilModels } from "./council/types"
11
12
 
@@ -124,7 +125,7 @@ export async function setup(options: SetupOptions): Promise<Modules> {
124
125
  for (const file of missing) {
125
126
  const raw = await fs.readFile(path.join(committedDir, file), "utf8")
126
127
  const entry = JSON.parse(raw) as import("./shared/types").ChronicleEntry
127
- const embeddingText = [entry.key_insight, ...entry.affected_areas].join(" ")
128
+ const embeddingText = [entryText(entry), ...entry.affected_areas, ...(entry.scope ?? [])].join(" ")
128
129
  const vector = await embedder(embeddingText)
129
130
  await vectorStore.upsert(entry.id, vector, entry)
130
131
  }
@@ -29,12 +29,19 @@ export type WorkRef = {
29
29
  /**
30
30
  * A durable knowledge record stored in Chronicle.
31
31
  * This is the canonical unit of institutional memory.
32
+ *
33
+ * Schema versions:
34
+ * v1 (no schema_version field): key_insight is the primary text field.
35
+ * v2 (schema_version: 2): decision is the primary text field; key_insight is a copy
36
+ * of decision written for backwards compatibility. Always use entryText() to read.
32
37
  */
33
38
  export type ChronicleEntry = {
34
39
  id: string
35
- /** The core finding or decision, in one clear sentence. */
40
+
41
+ // ── v1 fields (required — always present) ───────────────────────────────
42
+ /** The core finding or decision, in one clear sentence. v2: copy of decision. */
36
43
  key_insight: string
37
- /** Parts of the codebase or system this entry applies to. */
44
+ /** File paths or system areas this entry applies to. Used by Sentinel for file matching. */
38
45
  affected_areas: string[]
39
46
  status: "validated" | "refuted" | "open"
40
47
  /** 0–1. How strongly this was confirmed at write time. */
@@ -48,6 +55,44 @@ export type ChronicleEntry = {
48
55
  /** The unit of work that triggered this entry. Used to build SUMMARY.md temporal context. */
49
56
  work_ref?: WorkRef
50
57
  timestamp: string
58
+
59
+ // ── outcome tracking fields (optional — filled in post-execution) ────────────
60
+ /** Steps that must pass to confirm this decision was correct. */
61
+ validation_plan?: string[]
62
+ /** ISO date after which this entry should be re-evaluated for drift. */
63
+ review_after?: string
64
+ /** What actually happened after the decision was acted on in production. */
65
+ post_merge_result?: "successful" | "bug" | "partial" | "rolled-back"
66
+
67
+ // ── v2 fields (optional — absent on legacy entries) ──────────────────────
68
+ /** 2 = decision record format. Absent = v1 legacy entry. */
69
+ schema_version?: 2
70
+ /** Short label for this decision. e.g. "auth/session strategy" */
71
+ topic?: string
72
+ /** The decision itself — the primary text field in v2. Use entryText() to read. */
73
+ decision?: string
74
+ /** Domain/category tags. Additive — does NOT replace affected_areas. e.g. ["auth", "sessions"] */
75
+ scope?: string[]
76
+ /** Approaches that were considered but not chosen. */
77
+ alternatives_considered?: string[]
78
+ /** Why the alternatives were rejected. */
79
+ rejected_reason?: string[]
80
+ /** ID of the Chronicle entry this supersedes. */
81
+ supersedes?: string | null
82
+ /** ID of the Chronicle entry that superseded this one. */
83
+ superseded_by?: string | null
84
+ }
85
+
86
+ /**
87
+ * Return the primary text for a Chronicle entry regardless of schema version.
88
+ * v2 entries use decision; v1 entries use key_insight.
89
+ * All callsites that render or embed entry text must use this function.
90
+ *
91
+ * Accepts any object with key_insight and optional decision — works for both
92
+ * full ChronicleEntry and Omit<ChronicleEntry, "id" | "timestamp"> from propose().
93
+ */
94
+ export function entryText(entry: { key_insight: string; decision?: string }): string {
95
+ return entry.decision ?? entry.key_insight
51
96
  }
52
97
 
53
98
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@balpal4495/quorum",
3
- "version": "0.1.10",
3
+ "version": "0.3.0",
4
4
  "description": "Portable reasoning layer for agentic codebases — Oracle, Jury, Council, Sentinel",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -24,7 +24,7 @@
24
24
  },
25
25
  "scripts": {
26
26
  "init": "node bin/init.js",
27
- "test": "vitest run modules/",
27
+ "test": "vitest run modules/ evals/",
28
28
  "test:watch": "vitest modules/",
29
29
  "typecheck": "tsc --noEmit"
30
30
  },