@maestrofrontier/frontier 1.4.5 → 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 (50) hide show
  1. package/.agents/plugins/marketplace.json +21 -21
  2. package/.codex-plugin/plugin.json +29 -29
  3. package/.cursorrules +197 -194
  4. package/AGENTS.md +3 -3
  5. package/README.md +368 -368
  6. package/bin/maestro.cjs +75 -75
  7. package/commands/compress.md +36 -36
  8. package/commands/frontier.md +124 -124
  9. package/commands/terse.md +23 -23
  10. package/docs/codex.md +167 -167
  11. package/docs/orchestration.md +168 -168
  12. package/frontier/cli.cjs +279 -252
  13. package/frontier/config.cjs +468 -468
  14. package/frontier/dispatch.cjs +267 -255
  15. package/frontier/judge.cjs +92 -92
  16. package/frontier/run.cjs +201 -180
  17. package/frontier/schema.cjs +112 -112
  18. package/frontier/semaphore.cjs +49 -49
  19. package/frontier/synthesize.cjs +79 -79
  20. package/hooks/frontier-autorun.cjs +127 -120
  21. package/hooks/hooks.json +103 -103
  22. package/hooks/maestro-doctrine-guard.cjs +81 -81
  23. package/hooks/maestro-gate-reminder.cjs +22 -7
  24. package/hooks/maestro-gate-telemetry.cjs +79 -77
  25. package/hooks/maestro-phase-scope.cjs +118 -118
  26. package/hooks/maestro-statusline-sync.cjs +152 -152
  27. package/hooks/maestro-subagent-guard.cjs +148 -148
  28. package/hooks/maestro-terse-mode.cjs +189 -189
  29. package/hooks/maestro-toolbudget-advisory.cjs +127 -127
  30. package/integrations/README.md +111 -111
  31. package/integrations/cline/skills/frontier/SKILL.md +75 -75
  32. package/integrations/codex/prompts/frontier.md +70 -70
  33. package/integrations/codex/prompts/update.md +39 -39
  34. package/integrations/codex/skills/maestro-frontier/SKILL.md +122 -122
  35. package/integrations/codex/skills/maestro-settings/SKILL.md +55 -55
  36. package/integrations/codex/skills/maestro-terse/SKILL.md +58 -58
  37. package/integrations/codex/skills/maestro-update/SKILL.md +31 -31
  38. package/integrations/cursor/commands/frontier.md +63 -63
  39. package/integrations/cursor/commands/update.md +34 -34
  40. package/integrations/gemini/commands/frontier.toml +76 -76
  41. package/integrations/windsurf/workflows/frontier.md +70 -70
  42. package/package.json +58 -58
  43. package/scripts/install.cjs +1014 -1014
  44. package/settings/cli.cjs +140 -140
  45. package/settings/config.cjs +309 -309
  46. package/skills/maestro-frontier/SKILL.md +122 -122
  47. package/skills/maestro-settings/SKILL.md +55 -55
  48. package/skills/maestro-terse/SKILL.md +58 -58
  49. package/skills/maestro-update/SKILL.md +31 -31
  50. package/skills/terse/SKILL.md +74 -74
@@ -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 };