@damian87/omp 0.3.0 → 0.4.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.
Files changed (38) hide show
  1. package/.github/skills/weighted-consensus/SKILL.md +128 -0
  2. package/README.md +75 -1
  3. package/catalog/capabilities.json +46 -0
  4. package/catalog/skills-general.json +29 -1
  5. package/dist/src/cli.d.ts +8 -0
  6. package/dist/src/cli.js +125 -1
  7. package/dist/src/cli.js.map +1 -1
  8. package/dist/src/council/config.d.ts +33 -0
  9. package/dist/src/council/config.js +89 -0
  10. package/dist/src/council/config.js.map +1 -0
  11. package/dist/src/council/engine.d.ts +21 -0
  12. package/dist/src/council/engine.js +216 -0
  13. package/dist/src/council/engine.js.map +1 -0
  14. package/dist/src/council/index.d.ts +20 -0
  15. package/dist/src/council/index.js +72 -0
  16. package/dist/src/council/index.js.map +1 -0
  17. package/dist/src/council/prompts.d.ts +32 -0
  18. package/dist/src/council/prompts.js +172 -0
  19. package/dist/src/council/prompts.js.map +1 -0
  20. package/dist/src/council/synth.d.ts +15 -0
  21. package/dist/src/council/synth.js +57 -0
  22. package/dist/src/council/synth.js.map +1 -0
  23. package/dist/src/council/types.d.ts +98 -0
  24. package/dist/src/council/types.js +4 -0
  25. package/dist/src/council/types.js.map +1 -0
  26. package/package.json +3 -1
  27. package/dist/test/catalog.test.d.ts +0 -1
  28. package/dist/test/catalog.test.js +0 -21
  29. package/dist/test/catalog.test.js.map +0 -1
  30. package/dist/test/jira.test.d.ts +0 -1
  31. package/dist/test/jira.test.js +0 -26
  32. package/dist/test/jira.test.js.map +0 -1
  33. package/dist/test/lint.test.d.ts +0 -1
  34. package/dist/test/lint.test.js +0 -9
  35. package/dist/test/lint.test.js.map +0 -1
  36. package/dist/test/sync.test.d.ts +0 -1
  37. package/dist/test/sync.test.js +0 -15
  38. package/dist/test/sync.test.js.map +0 -1
@@ -0,0 +1,33 @@
1
+ import type { CouncilMemberSpec, CouncilTaskSpec, ResolvedCouncilConfig } from "./types.js";
2
+ export declare const DEFAULT_MIN_SURVIVORS = 2;
3
+ export declare const DEFAULT_PER_MEMBER_TIMEOUT_MS = 120000;
4
+ export declare const DEFAULT_MAX_CONCURRENCY = 4;
5
+ /**
6
+ * Built-in default roster. Uses the free/included lightweight models verified
7
+ * available via the Task 0 spike (gpt-5-mini, gpt-4.1) so the council runs
8
+ * without consuming premium model quota. Users override these in
9
+ * .omp/config.json `council` or inline via --models (e.g. add a Claude member
10
+ * for cross-provider diversity if their plan includes it).
11
+ */
12
+ export declare const DEFAULT_MEMBERS: CouncilMemberSpec[];
13
+ export declare const DEFAULT_SYNTHESIZER = "gpt-4.1";
14
+ interface PartialCouncilFileConfig {
15
+ members?: unknown;
16
+ synthesizer?: unknown;
17
+ minSurvivors?: unknown;
18
+ perMemberTimeoutMs?: unknown;
19
+ synthTimeoutMs?: unknown;
20
+ maxConcurrency?: unknown;
21
+ probe?: unknown;
22
+ }
23
+ export interface LoadCouncilConfigOptions {
24
+ cwd?: string;
25
+ }
26
+ /** Read the `council` block from .omp/config.json; tolerate missing/malformed. */
27
+ export declare function readCouncilFileConfig(options?: LoadCouncilConfigOptions): PartialCouncilFileConfig;
28
+ /**
29
+ * Resolve the effective council configuration.
30
+ * Precedence: spec override > .omp/config.json council block > built-in default.
31
+ */
32
+ export declare function loadCouncilConfig(spec?: CouncilTaskSpec, options?: LoadCouncilConfigOptions): ResolvedCouncilConfig;
33
+ export {};
@@ -0,0 +1,89 @@
1
+ import { existsSync, readFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ export const DEFAULT_MIN_SURVIVORS = 2;
4
+ export const DEFAULT_PER_MEMBER_TIMEOUT_MS = 120000;
5
+ export const DEFAULT_MAX_CONCURRENCY = 4;
6
+ /**
7
+ * Built-in default roster. Uses the free/included lightweight models verified
8
+ * available via the Task 0 spike (gpt-5-mini, gpt-4.1) so the council runs
9
+ * without consuming premium model quota. Users override these in
10
+ * .omp/config.json `council` or inline via --models (e.g. add a Claude member
11
+ * for cross-provider diversity if their plan includes it).
12
+ */
13
+ export const DEFAULT_MEMBERS = [
14
+ { model: "gpt-5-mini", role: "critic", weight: 0.4 },
15
+ { model: "gpt-4.1", role: "architect", weight: 0.35 },
16
+ { model: "gpt-5-mini", role: "pragmatist", weight: 0.25 },
17
+ ];
18
+ export const DEFAULT_SYNTHESIZER = "gpt-4.1";
19
+ function isValidMember(value) {
20
+ if (typeof value !== "object" || value === null)
21
+ return false;
22
+ const m = value;
23
+ return (typeof m.model === "string" &&
24
+ m.model.length > 0 &&
25
+ typeof m.role === "string" &&
26
+ m.role.length > 0 &&
27
+ typeof m.weight === "number" &&
28
+ Number.isFinite(m.weight) &&
29
+ m.weight > 0);
30
+ }
31
+ /** Read the `council` block from .omp/config.json; tolerate missing/malformed. */
32
+ export function readCouncilFileConfig(options = {}) {
33
+ const cwd = options.cwd ?? process.cwd();
34
+ const configFile = join(cwd, ".omp", "config.json");
35
+ if (!existsSync(configFile))
36
+ return {};
37
+ try {
38
+ const parsed = JSON.parse(readFileSync(configFile, "utf8"));
39
+ return parsed.council ?? {};
40
+ }
41
+ catch {
42
+ return {}; // unreadable/invalid config -> treat as absent
43
+ }
44
+ }
45
+ /**
46
+ * Resolve the effective council configuration.
47
+ * Precedence: spec override > .omp/config.json council block > built-in default.
48
+ */
49
+ export function loadCouncilConfig(spec = { question: "" }, options = {}) {
50
+ const file = readCouncilFileConfig(options);
51
+ const fileMembers = Array.isArray(file.members)
52
+ ? file.members.filter(isValidMember)
53
+ : [];
54
+ const members = spec.members && spec.members.length > 0
55
+ ? spec.members
56
+ : fileMembers.length > 0
57
+ ? fileMembers
58
+ : DEFAULT_MEMBERS;
59
+ const synthesizerModel = spec.synthesizerModel ??
60
+ (typeof file.synthesizer === "string" && file.synthesizer.length > 0
61
+ ? file.synthesizer
62
+ : DEFAULT_SYNTHESIZER);
63
+ const minSurvivors = spec.minSurvivors ??
64
+ (typeof file.minSurvivors === "number" ? file.minSurvivors : DEFAULT_MIN_SURVIVORS);
65
+ const perMemberTimeoutMs = spec.perMemberTimeoutMs ??
66
+ (typeof file.perMemberTimeoutMs === "number"
67
+ ? file.perMemberTimeoutMs
68
+ : DEFAULT_PER_MEMBER_TIMEOUT_MS);
69
+ const synthTimeoutMs = spec.synthTimeoutMs ??
70
+ (typeof file.synthTimeoutMs === "number"
71
+ ? file.synthTimeoutMs
72
+ : perMemberTimeoutMs * 2);
73
+ const maxConcurrency = spec.maxConcurrency ??
74
+ (typeof file.maxConcurrency === "number"
75
+ ? file.maxConcurrency
76
+ : DEFAULT_MAX_CONCURRENCY);
77
+ // probe precedence: spec.probe ?? config.probe ?? false
78
+ const probe = spec.probe ?? (typeof file.probe === "boolean" ? file.probe : false);
79
+ return {
80
+ members,
81
+ synthesizerModel,
82
+ minSurvivors,
83
+ perMemberTimeoutMs,
84
+ synthTimeoutMs,
85
+ maxConcurrency: maxConcurrency > 0 ? maxConcurrency : DEFAULT_MAX_CONCURRENCY,
86
+ probe,
87
+ };
88
+ }
89
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/council/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import { type LoadCouncilConfigOptions } from "./config.js";
2
+ import type { CouncilDeps, CouncilRunResult, CouncilTaskSpec } from "./types.js";
3
+ export type ProgressCallback = (message: string) => void;
4
+ /**
5
+ * Run `worker` over `items` with at most `limit` in flight. The slot is released
6
+ * in a finally block so a rejected/errored worker frees its slot too (otherwise
7
+ * a rejection would deadlock the queue for subsequent items). Results preserve
8
+ * input order. Worker rejections are reflected as rejected result promises, so
9
+ * callers should make `worker` non-throwing (we do).
10
+ */
11
+ export declare function runWithConcurrency<T, R>(items: T[], limit: number, worker: (item: T, index: number) => Promise<R>): Promise<R[]>;
12
+ export interface RunCouncilOptions extends LoadCouncilConfigOptions {
13
+ onProgress?: ProgressCallback;
14
+ }
15
+ /**
16
+ * Fan a question out to the council, parse + classify each member, then
17
+ * synthesize from survivors. Degrades gracefully: drops timed-out / unavailable /
18
+ * errored / unparseable members and synthesizes from the rest; fails only if
19
+ * fewer than `minSurvivors` survive.
20
+ */
21
+ export declare function runCouncil(spec: CouncilTaskSpec, deps: CouncilDeps, options?: RunCouncilOptions): Promise<CouncilRunResult>;
@@ -0,0 +1,216 @@
1
+ import { tmpdir } from "node:os";
2
+ import { join } from "node:path";
3
+ import { loadCouncilConfig } from "./config.js";
4
+ import { buildMemberPrompt, parseMemberOutput } from "./prompts.js";
5
+ import { synthesize } from "./synth.js";
6
+ /** stderr signature emitted by copilot when a --model slug is not entitled. */
7
+ const UNAVAILABLE_SIGNATURE = /is not available/i;
8
+ function isUnavailable(res) {
9
+ return res.exitCode !== 0 && !res.timedOut && UNAVAILABLE_SIGNATURE.test(res.stderr);
10
+ }
11
+ /**
12
+ * Run `worker` over `items` with at most `limit` in flight. The slot is released
13
+ * in a finally block so a rejected/errored worker frees its slot too (otherwise
14
+ * a rejection would deadlock the queue for subsequent items). Results preserve
15
+ * input order. Worker rejections are reflected as rejected result promises, so
16
+ * callers should make `worker` non-throwing (we do).
17
+ */
18
+ export async function runWithConcurrency(items, limit, worker) {
19
+ const results = new Array(items.length);
20
+ let next = 0;
21
+ const effectiveLimit = Math.max(1, Math.min(limit, items.length || 1));
22
+ async function runner() {
23
+ while (true) {
24
+ const current = next++;
25
+ if (current >= items.length)
26
+ return;
27
+ try {
28
+ results[current] = await worker(items[current], current);
29
+ }
30
+ finally {
31
+ // slot is freed simply by looping to the next item
32
+ }
33
+ }
34
+ }
35
+ const runners = [];
36
+ for (let i = 0; i < effectiveLimit; i++)
37
+ runners.push(runner());
38
+ await Promise.all(runners);
39
+ return results;
40
+ }
41
+ function classify(res) {
42
+ if (res.timedOut)
43
+ return { status: "timeout", dropReason: "member timed out" };
44
+ if (isUnavailable(res)) {
45
+ return { status: "unavailable", dropReason: "model not available to this Copilot plan" };
46
+ }
47
+ if (res.exitCode !== 0) {
48
+ return { status: "error", dropReason: `member exited ${res.exitCode}` };
49
+ }
50
+ return { status: "ok" };
51
+ }
52
+ async function runMember(spec, index, taskSpec, config, deps, tmpDir) {
53
+ const prompt = buildMemberPrompt(taskSpec, spec);
54
+ const started = (deps.now ?? Date.now)();
55
+ let res;
56
+ try {
57
+ res = await deps.spawn({ model: spec.model, prompt, timeoutMs: config.perMemberTimeoutMs });
58
+ }
59
+ catch (err) {
60
+ return {
61
+ spec,
62
+ status: "error",
63
+ durationMs: 0,
64
+ dropReason: `spawn failed: ${String(err)}`,
65
+ };
66
+ }
67
+ const durationMs = (deps.now ?? Date.now)() - started;
68
+ let { status, dropReason } = classify(res);
69
+ let output;
70
+ if (status === "ok" || status === "timeout") {
71
+ const parsed = parseMemberOutput(res.stdout);
72
+ if (parsed) {
73
+ // Upgrade timed-out members that produced valid output before the kill.
74
+ if (status === "timeout") {
75
+ status = "ok";
76
+ dropReason = undefined;
77
+ }
78
+ output = parsed;
79
+ }
80
+ else if (status === "ok") {
81
+ status = "unparseable";
82
+ dropReason = "no schema-valid JSON in output";
83
+ }
84
+ // timeout with no parseable output stays "timeout"
85
+ }
86
+ const jsonPath = join(tmpDir, `m${index}.json`);
87
+ const artifact = output ?? { rawStdout: res.stdout, rawStderr: res.stderr, status };
88
+ if (deps.writeArtifact) {
89
+ try {
90
+ deps.writeArtifact(jsonPath, JSON.stringify(artifact, null, 2));
91
+ }
92
+ catch {
93
+ // artifact write is best-effort; ignore failures
94
+ }
95
+ }
96
+ return {
97
+ spec,
98
+ status,
99
+ output,
100
+ rawStdout: res.stdout,
101
+ rawStderr: res.stderr,
102
+ exitCode: res.exitCode,
103
+ durationMs,
104
+ dropReason,
105
+ jsonPath,
106
+ };
107
+ }
108
+ /**
109
+ * Opt-in preflight probe: cheaply ping each DISTINCT model and prune only those
110
+ * that report "unavailable" (exit + stderr signature). A slow/timed-out probe is
111
+ * NOT treated as unavailable, so reachable-but-slow models are kept.
112
+ */
113
+ async function probeRoster(members, config, deps) {
114
+ const distinct = Array.from(new Set(members.map((m) => m.model)));
115
+ const probeTimeout = Math.min(15000, config.perMemberTimeoutMs);
116
+ const verdicts = await runWithConcurrency(distinct, config.maxConcurrency, async (model) => {
117
+ try {
118
+ const res = await deps.spawn({ model, prompt: "Reply with: ok", timeoutMs: probeTimeout });
119
+ return { model, unavailable: isUnavailable(res) };
120
+ }
121
+ catch {
122
+ return { model, unavailable: false }; // spawn error != entitlement problem
123
+ }
124
+ });
125
+ const unavailable = new Set(verdicts.filter((v) => v.unavailable).map((v) => v.model));
126
+ const kept = members.filter((m) => !unavailable.has(m.model));
127
+ const pruned = members
128
+ .filter((m) => unavailable.has(m.model))
129
+ .map((m) => ({ model: m.model, reason: "model not available to this Copilot plan" }));
130
+ return { kept, pruned };
131
+ }
132
+ /**
133
+ * Fan a question out to the council, parse + classify each member, then
134
+ * synthesize from survivors. Degrades gracefully: drops timed-out / unavailable /
135
+ * errored / unparseable members and synthesizes from the rest; fails only if
136
+ * fewer than `minSurvivors` survive.
137
+ */
138
+ export async function runCouncil(spec, deps, options = {}) {
139
+ const config = loadCouncilConfig(spec, options);
140
+ const now = deps.now ?? Date.now;
141
+ const tmpDir = spec.tmpDir ?? join(tmpdir(), `council-${now()}`);
142
+ const progress = options.onProgress;
143
+ let roster = config.members;
144
+ const prunedResults = [];
145
+ if (config.probe) {
146
+ progress?.(`Probing ${roster.length} model(s)…`);
147
+ const { kept, pruned } = await probeRoster(roster, config, deps);
148
+ roster = kept;
149
+ for (const p of pruned) {
150
+ const spc = config.members.find((m) => m.model === p.model);
151
+ if (spc) {
152
+ progress?.(` ✗ ${spc.model} (${spc.role}): unavailable`);
153
+ prunedResults.push({
154
+ spec: spc,
155
+ status: "unavailable",
156
+ durationMs: 0,
157
+ dropReason: p.reason,
158
+ });
159
+ }
160
+ }
161
+ }
162
+ progress?.(`Running ${roster.length} member(s)…`);
163
+ let completed = 0;
164
+ const ran = await runWithConcurrency(roster, config.maxConcurrency, async (member, i) => {
165
+ const result = await runMember(member, i, spec, config, deps, tmpDir);
166
+ completed++;
167
+ const dur = (result.durationMs / 1000).toFixed(1);
168
+ if (result.status === "ok") {
169
+ progress?.(` ✓ ${completed}/${roster.length} ${member.model} (${member.role}) ${dur}s`);
170
+ }
171
+ else {
172
+ progress?.(` ✗ ${completed}/${roster.length} ${member.model} (${member.role}) ${result.status} ${dur}s`);
173
+ }
174
+ return result;
175
+ });
176
+ const members = [...ran, ...prunedResults];
177
+ const survivors = members.filter((m) => m.status === "ok");
178
+ const dropped = members.length - survivors.length;
179
+ if (survivors.length < config.minSurvivors) {
180
+ const unavailableModels = members
181
+ .filter((m) => m.status === "unavailable")
182
+ .map((m) => m.spec.model);
183
+ const detail = unavailableModels.length > 0
184
+ ? ` Unavailable models: ${unavailableModels.join(", ")}.`
185
+ : "";
186
+ return {
187
+ ok: false,
188
+ members,
189
+ survivors: survivors.length,
190
+ dropped,
191
+ tmpDir,
192
+ error: `too few surviving members (${survivors.length}/${config.minSurvivors}).${detail}`,
193
+ };
194
+ }
195
+ progress?.(`Synthesizing from ${survivors.length} survivor(s)…`);
196
+ const synthResult = await synthesize(config, spec, members, deps);
197
+ if (!synthResult.ok || !synthResult.synth) {
198
+ return {
199
+ ok: false,
200
+ members,
201
+ survivors: survivors.length,
202
+ dropped,
203
+ tmpDir,
204
+ error: synthResult.error ?? "synthesis failed",
205
+ };
206
+ }
207
+ return {
208
+ ok: true,
209
+ synth: synthResult.synth,
210
+ members,
211
+ survivors: survivors.length,
212
+ dropped,
213
+ tmpDir,
214
+ };
215
+ }
216
+ //# sourceMappingURL=engine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.js","sourceRoot":"","sources":["../../../src/council/engine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import { type RunCouncilOptions } from "./engine.js";
2
+ import type { CouncilDeps, CouncilRunResult, CouncilSpawn, CouncilTaskSpec } from "./types.js";
3
+ export * from "./types.js";
4
+ export { loadCouncilConfig, readCouncilFileConfig, DEFAULT_MEMBERS, DEFAULT_SYNTHESIZER, DEFAULT_MIN_SURVIVORS, DEFAULT_PER_MEMBER_TIMEOUT_MS, DEFAULT_MAX_CONCURRENCY, } from "./config.js";
5
+ export { buildMemberPrompt, buildSynthPrompt, parseMemberOutput, parseSynthOutput, extractJsonCandidates, balancedBlocks, isValidMemberOutput, isValidSynthOutput, } from "./prompts.js";
6
+ export { runCouncil, runWithConcurrency, type ProgressCallback } from "./engine.js";
7
+ export { synthesize } from "./synth.js";
8
+ /**
9
+ * Default member invoker: spawn `copilot --model <model> -p <prompt> --allow-all-tools`
10
+ * with PIPED stdio so we can capture stdout. Uses resolveCopilotBin() so the
11
+ * OMP_COPILOT_BIN stub-bin test seam works. Does NOT route through launchCopilot
12
+ * (that tmux-wraps and inherits stdio, which would discard the model's output).
13
+ */
14
+ export declare function createDefaultSpawn(bin?: string): CouncilSpawn;
15
+ /** Default deps: real spawn + fs artifact writer (mkdir -p on demand). */
16
+ export declare function createDefaultDeps(bin?: string): CouncilDeps;
17
+ /** Convenience entry for the CLI: run the council with the real default deps. */
18
+ export declare function runCouncilWithDefaults(spec: CouncilTaskSpec, options?: RunCouncilOptions & {
19
+ bin?: string;
20
+ }): Promise<CouncilRunResult>;
@@ -0,0 +1,72 @@
1
+ import { spawn } from "node:child_process";
2
+ import { mkdirSync, writeFileSync } from "node:fs";
3
+ import { dirname } from "node:path";
4
+ import { resolveCopilotBin } from "../copilot/launch.js";
5
+ import { runCouncil } from "./engine.js";
6
+ export * from "./types.js";
7
+ export { loadCouncilConfig, readCouncilFileConfig, DEFAULT_MEMBERS, DEFAULT_SYNTHESIZER, DEFAULT_MIN_SURVIVORS, DEFAULT_PER_MEMBER_TIMEOUT_MS, DEFAULT_MAX_CONCURRENCY, } from "./config.js";
8
+ export { buildMemberPrompt, buildSynthPrompt, parseMemberOutput, parseSynthOutput, extractJsonCandidates, balancedBlocks, isValidMemberOutput, isValidSynthOutput, } from "./prompts.js";
9
+ export { runCouncil, runWithConcurrency } from "./engine.js";
10
+ export { synthesize } from "./synth.js";
11
+ /**
12
+ * Default member invoker: spawn `copilot --model <model> -p <prompt> --allow-all-tools`
13
+ * with PIPED stdio so we can capture stdout. Uses resolveCopilotBin() so the
14
+ * OMP_COPILOT_BIN stub-bin test seam works. Does NOT route through launchCopilot
15
+ * (that tmux-wraps and inherits stdio, which would discard the model's output).
16
+ */
17
+ export function createDefaultSpawn(bin) {
18
+ const copilotBin = resolveCopilotBin(bin);
19
+ return (req) => new Promise((resolveFn) => {
20
+ const child = spawn(copilotBin, ["--model", req.model, "-p", req.prompt, "--allow-all-tools"], { stdio: ["ignore", "pipe", "pipe"] });
21
+ let stdout = "";
22
+ let stderr = "";
23
+ let timedOut = false;
24
+ let settled = false;
25
+ const timer = setTimeout(() => {
26
+ timedOut = true;
27
+ child.kill("SIGTERM");
28
+ }, req.timeoutMs);
29
+ child.stdout?.on("data", (d) => {
30
+ stdout += d.toString();
31
+ });
32
+ child.stderr?.on("data", (d) => {
33
+ stderr += d.toString();
34
+ });
35
+ child.on("error", () => {
36
+ if (settled)
37
+ return;
38
+ settled = true;
39
+ clearTimeout(timer);
40
+ resolveFn({ stdout, stderr, exitCode: 127, timedOut });
41
+ });
42
+ child.on("close", (code) => {
43
+ if (settled)
44
+ return;
45
+ settled = true;
46
+ clearTimeout(timer);
47
+ resolveFn({
48
+ stdout,
49
+ stderr,
50
+ exitCode: typeof code === "number" ? code : timedOut ? 124 : 1,
51
+ timedOut,
52
+ });
53
+ });
54
+ });
55
+ }
56
+ /** Default deps: real spawn + fs artifact writer (mkdir -p on demand). */
57
+ export function createDefaultDeps(bin) {
58
+ return {
59
+ spawn: createDefaultSpawn(bin),
60
+ now: () => Date.now(),
61
+ writeArtifact: (path, data) => {
62
+ mkdirSync(dirname(path), { recursive: true });
63
+ writeFileSync(path, data, "utf8");
64
+ },
65
+ };
66
+ }
67
+ /** Convenience entry for the CLI: run the council with the real default deps. */
68
+ export async function runCouncilWithDefaults(spec, options = {}) {
69
+ const { bin, ...rest } = options;
70
+ return runCouncil(spec, createDefaultDeps(bin), rest);
71
+ }
72
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/council/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ import type { CouncilMemberOutput, CouncilMemberResult, CouncilMemberSpec, CouncilSynthOutput, CouncilTaskSpec, ResolvedCouncilConfig } from "./types.js";
2
+ /**
3
+ * Build a concise member prompt. Role is injected via {{COUNCIL_ROLE}}.
4
+ * Members are told to wrap their JSON in sentinels so the engine can extract it
5
+ * reliably from fence/banner noise (verified necessary in the Task 0 spike).
6
+ * NOTE: sentinels are NOT a security boundary — a hostile --context could embed
7
+ * the markers; the engine schema-validates extracted blocks to mitigate.
8
+ */
9
+ export declare function buildMemberPrompt(spec: CouncilTaskSpec, member: CouncilMemberSpec): string;
10
+ /** Build the low-context synthesizer prompt from surviving members. */
11
+ export declare function buildSynthPrompt(config: ResolvedCouncilConfig, spec: CouncilTaskSpec, survivors: CouncilMemberResult[]): string;
12
+ /**
13
+ * Enumerate top-level balanced {...} blocks in text (brace-depth scan).
14
+ * Returns the raw substrings in order of appearance.
15
+ */
16
+ export declare function balancedBlocks(text: string): string[];
17
+ /**
18
+ * Extract candidate JSON strings from raw stdout. Sentinel-wrapped content is
19
+ * preferred (primary contract); otherwise fall back to all balanced {...} blocks.
20
+ */
21
+ export declare function extractJsonCandidates(stdout: string): string[];
22
+ export declare function isValidMemberOutput(value: unknown): value is CouncilMemberOutput;
23
+ export declare function isValidSynthOutput(value: unknown): value is CouncilSynthOutput;
24
+ /**
25
+ * Parse a member's stdout into a validated CouncilMemberOutput.
26
+ * Strategy: enumerate candidate blocks, JSON.parse each, return the FIRST that
27
+ * passes schema validation. Tie-break = schema validity, not size/position.
28
+ * Returns null when no candidate validates (caller marks "unparseable").
29
+ */
30
+ export declare function parseMemberOutput(stdout: string): CouncilMemberOutput | null;
31
+ /** Parse the synthesizer's stdout into a validated CouncilSynthOutput. */
32
+ export declare function parseSynthOutput(stdout: string): CouncilSynthOutput | null;