@maestrofrontier/frontier 1.4.4 → 1.5.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 (53) hide show
  1. package/.agents/plugins/marketplace.json +21 -0
  2. package/.codex-plugin/plugin.json +29 -0
  3. package/.cursorrules +197 -194
  4. package/AGENTS.md +214 -214
  5. package/CLAUDE.md +29 -29
  6. package/README.md +368 -278
  7. package/bin/maestro.cjs +75 -75
  8. package/commands/compress.md +36 -36
  9. package/commands/frontier.md +124 -124
  10. package/commands/terse.md +23 -23
  11. package/docs/codex.md +167 -98
  12. package/docs/orchestration.md +168 -168
  13. package/frontier/cli.cjs +279 -248
  14. package/frontier/config.cjs +468 -441
  15. package/frontier/dispatch.cjs +267 -255
  16. package/frontier/judge.cjs +92 -92
  17. package/frontier/run.cjs +201 -148
  18. package/frontier/schema.cjs +112 -112
  19. package/frontier/semaphore.cjs +49 -49
  20. package/frontier/synthesize.cjs +79 -79
  21. package/hooks/frontier-autorun.cjs +127 -124
  22. package/hooks/hooks.json +103 -103
  23. package/hooks/maestro-doctrine-guard.cjs +81 -81
  24. package/hooks/maestro-gate-reminder.cjs +22 -7
  25. package/hooks/maestro-gate-telemetry.cjs +79 -77
  26. package/hooks/maestro-phase-scope.cjs +118 -118
  27. package/hooks/maestro-statusline-sync.cjs +152 -152
  28. package/hooks/maestro-subagent-guard.cjs +148 -148
  29. package/hooks/maestro-terse-mode.cjs +189 -189
  30. package/hooks/maestro-toolbudget-advisory.cjs +127 -127
  31. package/integrations/README.md +111 -94
  32. package/integrations/cline/skills/frontier/SKILL.md +75 -75
  33. package/integrations/codex/prompts/frontier.md +70 -66
  34. package/integrations/codex/prompts/update.md +39 -36
  35. package/integrations/codex/skills/maestro-frontier/SKILL.md +122 -0
  36. package/integrations/codex/skills/{settings → maestro-settings}/SKILL.md +55 -46
  37. package/integrations/codex/skills/{terse → maestro-terse}/SKILL.md +58 -49
  38. package/integrations/codex/skills/maestro-update/SKILL.md +31 -0
  39. package/integrations/cursor/commands/frontier.md +63 -63
  40. package/integrations/cursor/commands/update.md +34 -34
  41. package/integrations/gemini/commands/frontier.toml +76 -76
  42. package/integrations/windsurf/workflows/frontier.md +70 -70
  43. package/package.json +58 -55
  44. package/scripts/install.cjs +1014 -605
  45. package/settings/cli.cjs +140 -140
  46. package/settings/config.cjs +309 -309
  47. package/skills/maestro-frontier/SKILL.md +122 -0
  48. package/skills/maestro-settings/SKILL.md +55 -0
  49. package/skills/maestro-terse/SKILL.md +58 -0
  50. package/skills/maestro-update/SKILL.md +31 -0
  51. package/skills/terse/SKILL.md +74 -0
  52. package/integrations/codex/skills/frontier/SKILL.md +0 -91
  53. package/integrations/codex/skills/update/SKILL.md +0 -29
@@ -1,112 +1,112 @@
1
- #!/usr/bin/env node
2
- // Maestro Frontier — shared types-as-validators + helpers.
3
- // Zero deps, CJS. Ported stripLlmWrapper from scripts/compress.cjs.
4
-
5
- 'use strict';
6
-
7
- /**
8
- * @typedef {{ model:string, content:string, ok:boolean, durationMs:number, tokensEst:number, toolCalls?:unknown[], error?:string }} PanelResponse
9
- * @typedef {{ model:string, reason:string }} FailedModel
10
- * @typedef {{ consensus:string[], contradictions:{topic:string,stances:{model:string,stance:string}[]}[], partial_coverage:{models:string[],point:string}[], unique_insights:{model:string,insight:string}[], blind_spots:string[] }} Analysis
11
- */
12
-
13
- /** @type {string[]} */
14
- const FAILURE_REASONS = [
15
- 'all_panels_failed',
16
- 'insufficient_credits',
17
- 'rate_limited',
18
- 'fusion_invocation_capped',
19
- 'unexpected_error',
20
- ];
21
-
22
- /**
23
- * @param {unknown} x
24
- * @returns {x is PanelResponse}
25
- */
26
- function isPanelResponse(x) {
27
- if (x === null || typeof x !== 'object') return false;
28
- const o = /** @type {Record<string,unknown>} */ (x);
29
- return (
30
- typeof o.model === 'string' &&
31
- typeof o.content === 'string' &&
32
- typeof o.ok === 'boolean' &&
33
- typeof o.durationMs === 'number' &&
34
- typeof o.tokensEst === 'number'
35
- );
36
- }
37
-
38
- /**
39
- * @param {unknown} x
40
- * @returns {x is Analysis}
41
- */
42
- function isAnalysis(x) {
43
- if (x === null || typeof x !== 'object') return false;
44
- const o = /** @type {Record<string,unknown>} */ (x);
45
- if (!Array.isArray(o.consensus)) return false;
46
- if (!o.consensus.every(s => typeof s === 'string')) return false;
47
- if (!Array.isArray(o.blind_spots)) return false;
48
- if (!o.blind_spots.every(s => typeof s === 'string')) return false;
49
- if (!Array.isArray(o.contradictions)) return false;
50
- if (!o.contradictions.every(e => e !== null && typeof e === 'object')) return false;
51
- if (!Array.isArray(o.partial_coverage)) return false;
52
- if (!o.partial_coverage.every(e => e !== null && typeof e === 'object')) return false;
53
- if (!Array.isArray(o.unique_insights)) return false;
54
- if (!o.unique_insights.every(e => e !== null && typeof e === 'object')) return false;
55
- return true;
56
- }
57
-
58
- /**
59
- * @param {string} str
60
- * @returns {Analysis}
61
- * @throws {Error}
62
- */
63
- function parseAnalysis(str) {
64
- let parsed;
65
- try {
66
- parsed = JSON.parse(str);
67
- } catch (e) {
68
- throw new Error('parseAnalysis: invalid JSON — ' + e.message);
69
- }
70
- if (!isAnalysis(parsed)) {
71
- throw new Error('parseAnalysis: object does not satisfy Analysis shape');
72
- }
73
- return /** @type {Analysis} */ (parsed);
74
- }
75
-
76
- /**
77
- * @param {PanelResponse} panelResponse
78
- * @returns {FailedModel}
79
- */
80
- function toFailedModel(panelResponse) {
81
- return { model: panelResponse.model, reason: panelResponse.error || 'unknown' };
82
- }
83
-
84
- /**
85
- * @param {FailedModel[]} failedModels
86
- * @returns {string}
87
- */
88
- function classify(failedModels) {
89
- if (!failedModels || failedModels.length === 0) return 'all_panels_failed';
90
- const combined = failedModels.map(f => f.reason || '').join(' ').toLowerCase();
91
- if (/rate.?limit|429|too many request/.test(combined)) return 'rate_limited';
92
- if (/insufficient|credit|quota|billing|payment|exceed.*(usage|plan)/.test(combined)) return 'insufficient_credits';
93
- if (/enoent|spawn|signal|crash|killed/.test(combined)) return 'unexpected_error';
94
- return 'all_panels_failed';
95
- }
96
-
97
- // Port VERBATIM from scripts/compress.cjs — strips an outer ```fence
98
- // wrapping the ENTIRE output.
99
- function stripLlmWrapper(text) {
100
- const m = text.match(/^\s*(`{3,}|~{3,})[^\n]*\n([\s\S]*)\n\1\s*$/);
101
- return m ? m[2] : text;
102
- }
103
-
104
- module.exports = {
105
- FAILURE_REASONS,
106
- isPanelResponse,
107
- isAnalysis,
108
- parseAnalysis,
109
- toFailedModel,
110
- classify,
111
- stripLlmWrapper,
112
- };
1
+ #!/usr/bin/env node
2
+ // Maestro Frontier — shared types-as-validators + helpers.
3
+ // Zero deps, CJS. Ported stripLlmWrapper from scripts/compress.cjs.
4
+
5
+ 'use strict';
6
+
7
+ /**
8
+ * @typedef {{ model:string, content:string, ok:boolean, durationMs:number, tokensEst:number, toolCalls?:unknown[], error?:string }} PanelResponse
9
+ * @typedef {{ model:string, reason:string }} FailedModel
10
+ * @typedef {{ consensus:string[], contradictions:{topic:string,stances:{model:string,stance:string}[]}[], partial_coverage:{models:string[],point:string}[], unique_insights:{model:string,insight:string}[], blind_spots:string[] }} Analysis
11
+ */
12
+
13
+ /** @type {string[]} */
14
+ const FAILURE_REASONS = [
15
+ 'all_panels_failed',
16
+ 'insufficient_credits',
17
+ 'rate_limited',
18
+ 'fusion_invocation_capped',
19
+ 'unexpected_error',
20
+ ];
21
+
22
+ /**
23
+ * @param {unknown} x
24
+ * @returns {x is PanelResponse}
25
+ */
26
+ function isPanelResponse(x) {
27
+ if (x === null || typeof x !== 'object') return false;
28
+ const o = /** @type {Record<string,unknown>} */ (x);
29
+ return (
30
+ typeof o.model === 'string' &&
31
+ typeof o.content === 'string' &&
32
+ typeof o.ok === 'boolean' &&
33
+ typeof o.durationMs === 'number' &&
34
+ typeof o.tokensEst === 'number'
35
+ );
36
+ }
37
+
38
+ /**
39
+ * @param {unknown} x
40
+ * @returns {x is Analysis}
41
+ */
42
+ function isAnalysis(x) {
43
+ if (x === null || typeof x !== 'object') return false;
44
+ const o = /** @type {Record<string,unknown>} */ (x);
45
+ if (!Array.isArray(o.consensus)) return false;
46
+ if (!o.consensus.every(s => typeof s === 'string')) return false;
47
+ if (!Array.isArray(o.blind_spots)) return false;
48
+ if (!o.blind_spots.every(s => typeof s === 'string')) return false;
49
+ if (!Array.isArray(o.contradictions)) return false;
50
+ if (!o.contradictions.every(e => e !== null && typeof e === 'object')) return false;
51
+ if (!Array.isArray(o.partial_coverage)) return false;
52
+ if (!o.partial_coverage.every(e => e !== null && typeof e === 'object')) return false;
53
+ if (!Array.isArray(o.unique_insights)) return false;
54
+ if (!o.unique_insights.every(e => e !== null && typeof e === 'object')) return false;
55
+ return true;
56
+ }
57
+
58
+ /**
59
+ * @param {string} str
60
+ * @returns {Analysis}
61
+ * @throws {Error}
62
+ */
63
+ function parseAnalysis(str) {
64
+ let parsed;
65
+ try {
66
+ parsed = JSON.parse(str);
67
+ } catch (e) {
68
+ throw new Error('parseAnalysis: invalid JSON — ' + e.message);
69
+ }
70
+ if (!isAnalysis(parsed)) {
71
+ throw new Error('parseAnalysis: object does not satisfy Analysis shape');
72
+ }
73
+ return /** @type {Analysis} */ (parsed);
74
+ }
75
+
76
+ /**
77
+ * @param {PanelResponse} panelResponse
78
+ * @returns {FailedModel}
79
+ */
80
+ function toFailedModel(panelResponse) {
81
+ return { model: panelResponse.model, reason: panelResponse.error || 'unknown' };
82
+ }
83
+
84
+ /**
85
+ * @param {FailedModel[]} failedModels
86
+ * @returns {string}
87
+ */
88
+ function classify(failedModels) {
89
+ if (!failedModels || failedModels.length === 0) return 'all_panels_failed';
90
+ const combined = failedModels.map(f => f.reason || '').join(' ').toLowerCase();
91
+ if (/rate.?limit|429|too many request/.test(combined)) return 'rate_limited';
92
+ if (/insufficient|credit|quota|billing|payment|exceed.*(usage|plan)/.test(combined)) return 'insufficient_credits';
93
+ if (/enoent|spawn|signal|crash|killed/.test(combined)) return 'unexpected_error';
94
+ return 'all_panels_failed';
95
+ }
96
+
97
+ // Port VERBATIM from scripts/compress.cjs — strips an outer ```fence
98
+ // wrapping the ENTIRE output.
99
+ function stripLlmWrapper(text) {
100
+ const m = text.match(/^\s*(`{3,}|~{3,})[^\n]*\n([\s\S]*)\n\1\s*$/);
101
+ return m ? m[2] : text;
102
+ }
103
+
104
+ module.exports = {
105
+ FAILURE_REASONS,
106
+ isPanelResponse,
107
+ isAnalysis,
108
+ parseAnalysis,
109
+ toFailedModel,
110
+ classify,
111
+ stripLlmWrapper,
112
+ };
@@ -1,49 +1,49 @@
1
- #!/usr/bin/env node
2
- // Maestro Frontier — bounded-concurrency map utility.
3
- // mapLimit(items, limit, asyncFn) -> Promise<settled[]>
4
- // Each settled item is {ok:true,value} or {ok:false,error}.
5
- // A rejected task releases its permit and does NOT starve the pool.
6
-
7
- 'use strict';
8
-
9
- /**
10
- * @template T, R
11
- * @param {T[]} items
12
- * @param {number} limit
13
- * @param {(item: T, index: number) => Promise<R>} asyncFn
14
- * @returns {Promise<({ok:true,value:R}|{ok:false,error:unknown})[]}
15
- */
16
- function mapLimit(items, limit, asyncFn) {
17
- return new Promise((resolve) => {
18
- const n = items.length;
19
- if (n === 0) { resolve([]); return; }
20
-
21
- const results = new Array(n);
22
- let nextIdx = 0; // index of next item to start
23
- let inFlight = 0; // currently running tasks
24
- let done = 0; // settled tasks
25
-
26
- function run() {
27
- while (inFlight < limit && nextIdx < n) {
28
- const idx = nextIdx++;
29
- inFlight++;
30
- Promise.resolve()
31
- .then(() => asyncFn(items[idx], idx))
32
- .then(
33
- (value) => { results[idx] = { ok: true, value }; },
34
- (error) => { results[idx] = { ok: false, error }; }
35
- )
36
- .finally(() => {
37
- inFlight--;
38
- done++;
39
- if (done === n) { resolve(results); return; }
40
- run();
41
- });
42
- }
43
- }
44
-
45
- run();
46
- });
47
- }
48
-
49
- module.exports = { mapLimit };
1
+ #!/usr/bin/env node
2
+ // Maestro Frontier — bounded-concurrency map utility.
3
+ // mapLimit(items, limit, asyncFn) -> Promise<settled[]>
4
+ // Each settled item is {ok:true,value} or {ok:false,error}.
5
+ // A rejected task releases its permit and does NOT starve the pool.
6
+
7
+ 'use strict';
8
+
9
+ /**
10
+ * @template T, R
11
+ * @param {T[]} items
12
+ * @param {number} limit
13
+ * @param {(item: T, index: number) => Promise<R>} asyncFn
14
+ * @returns {Promise<({ok:true,value:R}|{ok:false,error:unknown})[]}
15
+ */
16
+ function mapLimit(items, limit, asyncFn) {
17
+ return new Promise((resolve) => {
18
+ const n = items.length;
19
+ if (n === 0) { resolve([]); return; }
20
+
21
+ const results = new Array(n);
22
+ let nextIdx = 0; // index of next item to start
23
+ let inFlight = 0; // currently running tasks
24
+ let done = 0; // settled tasks
25
+
26
+ function run() {
27
+ while (inFlight < limit && nextIdx < n) {
28
+ const idx = nextIdx++;
29
+ inFlight++;
30
+ Promise.resolve()
31
+ .then(() => asyncFn(items[idx], idx))
32
+ .then(
33
+ (value) => { results[idx] = { ok: true, value }; },
34
+ (error) => { results[idx] = { ok: false, error }; }
35
+ )
36
+ .finally(() => {
37
+ inFlight--;
38
+ done++;
39
+ if (done === n) { resolve(results); return; }
40
+ run();
41
+ });
42
+ }
43
+ }
44
+
45
+ run();
46
+ });
47
+ }
48
+
49
+ module.exports = { mapLimit };
@@ -1,79 +1,79 @@
1
- #!/usr/bin/env node
2
- // Maestro Frontier — synthesis stage: build prompt + invoke Opus for final answer.
3
-
4
- 'use strict';
5
-
6
- const dispatch = require('./dispatch.cjs');
7
-
8
- /**
9
- * Build the synthesis prompt for Opus.
10
- * @param {string} userPrompt
11
- * @param {{ analysis?: import('./schema.cjs').Analysis, responses: import('./schema.cjs').PanelResponse[] }} bundle
12
- * @param {object} cfg
13
- * @returns {string}
14
- */
15
- function buildSynthPrompt(userPrompt, bundle, cfg) {
16
- const antiMajority =
17
- 'Do NOT majority-vote or pick the most common answer; weigh correctness and evidence — ' +
18
- 'a single correct minority response outweighs a popular wrong one.';
19
-
20
- let groundingSection;
21
- if (bundle.analysis) {
22
- groundingSection =
23
- `PANEL ANALYSIS (structured):
24
- ${JSON.stringify(bundle.analysis, null, 2)}
25
-
26
- Ground your final answer in this analysis:
27
- - Adopt the consensus points as established facts.
28
- - RESOLVE contradictions by reasoning about which stance is most correct; do not dodge them.
29
- - Preserve unique insights that add value.
30
- - Address any blind spots the analysis identified.`;
31
- } else {
32
- const raw = bundle.responses.map(
33
- r => `### Response from ${r.model}\n${r.content}`
34
- ).join('\n\n');
35
- groundingSection =
36
- `RAW PANEL RESPONSES:
37
- ${raw}
38
-
39
- Ground your final answer in these responses.`;
40
- }
41
-
42
- return `You are a SYNTHESIZER producing the definitive final answer to a user question.
43
-
44
- USER QUESTION:
45
- ${userPrompt}
46
-
47
- ${groundingSection}
48
-
49
- IMPORTANT: ${antiMajority}
50
-
51
- Write the final answer as clear, direct prose. No JSON, no meta-commentary, no preamble about your process. Output the answer only.`;
52
- }
53
-
54
- /**
55
- * Run the synthesis stage. Returns the final answer string or '' on failure (degrades gracefully).
56
- * @param {string} userPrompt
57
- * @param {{ analysis?: import('./schema.cjs').Analysis, responses: import('./schema.cjs').PanelResponse[] }} bundle
58
- * @param {object} cfg
59
- * @param {{ spawn?: Function }} [deps]
60
- * @returns {Promise<string>}
61
- */
62
- async function runSynth(userPrompt, bundle, cfg, deps) {
63
- const spawn = (deps && deps.spawn) || dispatch.spawnOne;
64
- let r;
65
- try {
66
- r = await spawn(
67
- buildSynthPrompt(userPrompt, bundle, cfg),
68
- cfg.adapters[cfg.synthModel],
69
- { timeoutMs: cfg.timeoutMs, fusionDepth: 1 }
70
- );
71
- } catch {
72
- return '';
73
- }
74
-
75
- if (r && r.ok && r.content) return r.content;
76
- return '';
77
- }
78
-
79
- module.exports = { buildSynthPrompt, runSynth };
1
+ #!/usr/bin/env node
2
+ // Maestro Frontier — synthesis stage: build prompt + invoke Opus for final answer.
3
+
4
+ 'use strict';
5
+
6
+ const dispatch = require('./dispatch.cjs');
7
+
8
+ /**
9
+ * Build the synthesis prompt for Opus.
10
+ * @param {string} userPrompt
11
+ * @param {{ analysis?: import('./schema.cjs').Analysis, responses: import('./schema.cjs').PanelResponse[] }} bundle
12
+ * @param {object} cfg
13
+ * @returns {string}
14
+ */
15
+ function buildSynthPrompt(userPrompt, bundle, cfg) {
16
+ const antiMajority =
17
+ 'Do NOT majority-vote or pick the most common answer; weigh correctness and evidence — ' +
18
+ 'a single correct minority response outweighs a popular wrong one.';
19
+
20
+ let groundingSection;
21
+ if (bundle.analysis) {
22
+ groundingSection =
23
+ `PANEL ANALYSIS (structured):
24
+ ${JSON.stringify(bundle.analysis, null, 2)}
25
+
26
+ Ground your final answer in this analysis:
27
+ - Adopt the consensus points as established facts.
28
+ - RESOLVE contradictions by reasoning about which stance is most correct; do not dodge them.
29
+ - Preserve unique insights that add value.
30
+ - Address any blind spots the analysis identified.`;
31
+ } else {
32
+ const raw = bundle.responses.map(
33
+ r => `### Response from ${r.model}\n${r.content}`
34
+ ).join('\n\n');
35
+ groundingSection =
36
+ `RAW PANEL RESPONSES:
37
+ ${raw}
38
+
39
+ Ground your final answer in these responses.`;
40
+ }
41
+
42
+ return `You are a SYNTHESIZER producing the definitive final answer to a user question.
43
+
44
+ USER QUESTION:
45
+ ${userPrompt}
46
+
47
+ ${groundingSection}
48
+
49
+ IMPORTANT: ${antiMajority}
50
+
51
+ Write the final answer as clear, direct prose. No JSON, no meta-commentary, no preamble about your process. Output the answer only.`;
52
+ }
53
+
54
+ /**
55
+ * Run the synthesis stage. Returns the final answer string or '' on failure (degrades gracefully).
56
+ * @param {string} userPrompt
57
+ * @param {{ analysis?: import('./schema.cjs').Analysis, responses: import('./schema.cjs').PanelResponse[] }} bundle
58
+ * @param {object} cfg
59
+ * @param {{ spawn?: Function }} [deps]
60
+ * @returns {Promise<string>}
61
+ */
62
+ async function runSynth(userPrompt, bundle, cfg, deps) {
63
+ const spawn = (deps && deps.spawn) || dispatch.spawnOne;
64
+ let r;
65
+ try {
66
+ r = await spawn(
67
+ buildSynthPrompt(userPrompt, bundle, cfg),
68
+ cfg.adapters[cfg.synthModel],
69
+ { timeoutMs: cfg.timeoutMs, fusionDepth: 1 }
70
+ );
71
+ } catch {
72
+ return '';
73
+ }
74
+
75
+ if (r && r.ok && r.content) return r.content;
76
+ return '';
77
+ }
78
+
79
+ module.exports = { buildSynthPrompt, runSynth };