@damian87/omp 0.3.0 → 0.4.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.
@@ -0,0 +1,57 @@
1
+ import { buildSynthPrompt, parseSynthOutput } from "./prompts.js";
2
+ function buildPerMemberSummary(members) {
3
+ return members.map((r) => ({
4
+ model: r.spec.model,
5
+ role: r.spec.role,
6
+ weight: r.spec.weight,
7
+ verdict: r.output?.verdict ?? "",
8
+ confidence: r.output?.confidence ?? 0,
9
+ dropped: r.status !== "ok",
10
+ dropReason: r.status !== "ok" ? r.dropReason : undefined,
11
+ }));
12
+ }
13
+ /**
14
+ * Run the synthesizer over surviving members. Never fabricates a verdict: if the
15
+ * synth call fails or is unparseable, returns ok:false with the raw output.
16
+ * The returned synth's per_member_summary is authoritatively rebuilt from ALL
17
+ * members (including dropped ones) so the model can't omit a dropped member.
18
+ */
19
+ export async function synthesize(config, spec, allMembers, deps) {
20
+ const survivors = allMembers.filter((m) => m.status === "ok");
21
+ const prompt = buildSynthPrompt(config, spec, survivors);
22
+ let res;
23
+ try {
24
+ res = await deps.spawn({
25
+ model: config.synthesizerModel,
26
+ prompt,
27
+ timeoutMs: config.perMemberTimeoutMs,
28
+ });
29
+ }
30
+ catch (err) {
31
+ return { ok: false, error: `synth spawn failed: ${String(err)}` };
32
+ }
33
+ if (res.timedOut) {
34
+ return { ok: false, rawStdout: res.stdout, rawStderr: res.stderr, error: "synth timed out" };
35
+ }
36
+ if (res.exitCode !== 0) {
37
+ return {
38
+ ok: false,
39
+ rawStdout: res.stdout,
40
+ rawStderr: res.stderr,
41
+ error: `synth exited ${res.exitCode}`,
42
+ };
43
+ }
44
+ const parsed = parseSynthOutput(res.stdout);
45
+ if (!parsed) {
46
+ return {
47
+ ok: false,
48
+ rawStdout: res.stdout,
49
+ rawStderr: res.stderr,
50
+ error: "synth output unparseable",
51
+ };
52
+ }
53
+ // Authoritative summary from engine-side member records.
54
+ parsed.per_member_summary = buildPerMemberSummary(allMembers);
55
+ return { ok: true, synth: parsed, rawStdout: res.stdout, rawStderr: res.stderr };
56
+ }
57
+ //# sourceMappingURL=synth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"synth.js","sourceRoot":"","sources":["../../../src/council/synth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAkBlE,SAAS,qBAAqB,CAC5B,OAA8B;IAE9B,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACzB,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK;QACnB,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI;QACjB,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM;QACrB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,OAAO,IAAI,EAAE;QAChC,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,UAAU,IAAI,CAAC;QACrC,OAAO,EAAE,CAAC,CAAC,MAAM,KAAK,IAAI;QAC1B,UAAU,EAAE,CAAC,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS;KACzD,CAAC,CAAC,CAAC;AACN,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,MAA6B,EAC7B,IAAqB,EACrB,UAAiC,EACjC,IAAiB;IAEjB,MAAM,SAAS,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC;IAC9D,MAAM,MAAM,GAAG,gBAAgB,CAAC,MAAM,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;IAEzD,IAAI,GAAG,CAAC;IACR,IAAI,CAAC;QACH,GAAG,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC;YACrB,KAAK,EAAE,MAAM,CAAC,gBAAgB;YAC9B,MAAM;YACN,SAAS,EAAE,MAAM,CAAC,kBAAkB;SACrC,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,uBAAuB,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;IACpE,CAAC;IAED,IAAI,GAAG,CAAC,QAAQ,EAAE,CAAC;QACjB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,iBAAiB,EAAE,CAAC;IAC/F,CAAC;IACD,IAAI,GAAG,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO;YACL,EAAE,EAAE,KAAK;YACT,SAAS,EAAE,GAAG,CAAC,MAAM;YACrB,SAAS,EAAE,GAAG,CAAC,MAAM;YACrB,KAAK,EAAE,gBAAgB,GAAG,CAAC,QAAQ,EAAE;SACtC,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,gBAAgB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAC5C,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO;YACL,EAAE,EAAE,KAAK;YACT,SAAS,EAAE,GAAG,CAAC,MAAM;YACrB,SAAS,EAAE,GAAG,CAAC,MAAM;YACrB,KAAK,EAAE,0BAA0B;SAClC,CAAC;IACJ,CAAC;IAED,yDAAyD;IACzD,MAAM,CAAC,kBAAkB,GAAG,qBAAqB,CAAC,UAAU,CAAC,CAAC;IAC9D,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC;AACnF,CAAC"}
@@ -0,0 +1,96 @@
1
+ /** One council member: a model running under a role with a prior weight. */
2
+ export interface CouncilMemberSpec {
3
+ model: string;
4
+ role: string;
5
+ weight: number;
6
+ }
7
+ /** The task the council answers. Generic so /code-review etc. can reuse it. */
8
+ export interface CouncilTaskSpec {
9
+ question: string;
10
+ context?: string;
11
+ rubric?: string;
12
+ rolePack?: string;
13
+ members?: CouncilMemberSpec[];
14
+ minSurvivors?: number;
15
+ perMemberTimeoutMs?: number;
16
+ synthesizerModel?: string;
17
+ probe?: boolean;
18
+ maxConcurrency?: number;
19
+ tmpDir?: string;
20
+ }
21
+ /** What each member MUST emit (the member JSON contract). */
22
+ export interface CouncilMemberOutput {
23
+ verdict: string;
24
+ confidence: number;
25
+ rationale: string;
26
+ risks?: string[];
27
+ dissent?: string;
28
+ }
29
+ /** Per-member runtime classification. "unavailable" is distinct from "error". */
30
+ export type CouncilMemberStatus = "ok" | "timeout" | "error" | "unavailable" | "unparseable";
31
+ /** Per-member runtime result (engine-internal, surfaced in --json). */
32
+ export interface CouncilMemberResult {
33
+ spec: CouncilMemberSpec;
34
+ status: CouncilMemberStatus;
35
+ output?: CouncilMemberOutput;
36
+ rawStdout?: string;
37
+ rawStderr?: string;
38
+ exitCode?: number;
39
+ durationMs: number;
40
+ dropReason?: string;
41
+ jsonPath?: string;
42
+ }
43
+ export interface CouncilPerMemberSummary {
44
+ model: string;
45
+ role: string;
46
+ weight: number;
47
+ verdict: string;
48
+ confidence: number;
49
+ dropped: boolean;
50
+ dropReason?: string;
51
+ }
52
+ /** Synthesizer output schema (final verdict). */
53
+ export interface CouncilSynthOutput {
54
+ verdict: string;
55
+ confidence: number;
56
+ rationale: string;
57
+ minority_report: string;
58
+ per_member_summary: CouncilPerMemberSummary[];
59
+ }
60
+ /** Top-level engine result (what runCouncil returns / cli prints). */
61
+ export interface CouncilRunResult {
62
+ ok: boolean;
63
+ synth?: CouncilSynthOutput;
64
+ members: CouncilMemberResult[];
65
+ survivors: number;
66
+ dropped: number;
67
+ tmpDir: string;
68
+ error?: string;
69
+ }
70
+ /** Resolved configuration after merging spec > config > built-in default. */
71
+ export interface ResolvedCouncilConfig {
72
+ members: CouncilMemberSpec[];
73
+ synthesizerModel: string;
74
+ minSurvivors: number;
75
+ perMemberTimeoutMs: number;
76
+ maxConcurrency: number;
77
+ probe: boolean;
78
+ }
79
+ export interface SpawnRequest {
80
+ model: string;
81
+ prompt: string;
82
+ timeoutMs: number;
83
+ }
84
+ export interface SpawnResponse {
85
+ stdout: string;
86
+ stderr: string;
87
+ exitCode: number;
88
+ timedOut: boolean;
89
+ }
90
+ /** Real impl spawns `copilot --model <model> -p <prompt>`; tests inject a fake. */
91
+ export type CouncilSpawn = (req: SpawnRequest) => Promise<SpawnResponse>;
92
+ export interface CouncilDeps {
93
+ spawn: CouncilSpawn;
94
+ now?: () => number;
95
+ writeArtifact?: (path: string, data: string) => void;
96
+ }
@@ -0,0 +1,4 @@
1
+ // Type contracts for the weighted-consensus model council.
2
+ // See docs/plans / .omc/plans/weighted-consensus.md for the authoritative design.
3
+ export {};
4
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/council/types.ts"],"names":[],"mappings":"AAAA,2DAA2D;AAC3D,kFAAkF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@damian87/omp",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "GitHub Copilot project skills catalog and Jira handoff tools.",
5
5
  "type": "module",
6
6
  "publishConfig": {