@hegemonart/get-design-done 1.25.0 → 1.27.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.
- package/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +96 -0
- package/README.md +12 -6
- package/SKILL.md +3 -0
- package/agents/README.md +89 -0
- package/agents/design-reflector.md +43 -0
- package/agents/gdd-intel-updater.md +34 -1
- package/hooks/budget-enforcer.ts +143 -4
- package/package.json +1 -1
- package/reference/model-prices.md +40 -19
- package/reference/peer-cli-capabilities.md +151 -0
- package/reference/peer-protocols.md +266 -0
- package/reference/prices/antigravity.md +21 -0
- package/reference/prices/augment.md +21 -0
- package/reference/prices/claude.md +42 -0
- package/reference/prices/cline.md +23 -0
- package/reference/prices/codebuddy.md +21 -0
- package/reference/prices/codex.md +25 -0
- package/reference/prices/copilot.md +21 -0
- package/reference/prices/cursor.md +21 -0
- package/reference/prices/gemini.md +25 -0
- package/reference/prices/kilo.md +21 -0
- package/reference/prices/opencode.md +23 -0
- package/reference/prices/qwen.md +25 -0
- package/reference/prices/trae.md +23 -0
- package/reference/prices/windsurf.md +21 -0
- package/reference/registry.json +121 -1
- package/reference/runtime-models.md +446 -0
- package/reference/schemas/runtime-models.schema.json +123 -0
- package/scripts/install.cjs +8 -0
- package/scripts/lib/bandit-router.cjs +214 -7
- package/scripts/lib/budget-enforcer.cjs +514 -0
- package/scripts/lib/cost-arbitrage.cjs +294 -0
- package/scripts/lib/event-stream/index.ts +14 -1
- package/scripts/lib/event-stream/types.ts +125 -1
- package/scripts/lib/install/installer.cjs +188 -11
- package/scripts/lib/install/parse-runtime-models.cjs +267 -0
- package/scripts/lib/install/runtimes.cjs +101 -0
- package/scripts/lib/peer-cli/acp-client.cjs +375 -0
- package/scripts/lib/peer-cli/adapters/codex.cjs +101 -0
- package/scripts/lib/peer-cli/adapters/copilot.cjs +79 -0
- package/scripts/lib/peer-cli/adapters/cursor.cjs +78 -0
- package/scripts/lib/peer-cli/adapters/gemini.cjs +81 -0
- package/scripts/lib/peer-cli/adapters/qwen.cjs +72 -0
- package/scripts/lib/peer-cli/asp-client.cjs +587 -0
- package/scripts/lib/peer-cli/broker-lifecycle.cjs +406 -0
- package/scripts/lib/peer-cli/registry.cjs +434 -0
- package/scripts/lib/peer-cli/spawn-cmd.cjs +149 -0
- package/scripts/lib/runtime-detect.cjs +96 -0
- package/scripts/lib/session-runner/index.ts +215 -0
- package/scripts/lib/session-runner/types.ts +60 -0
- package/scripts/lib/tier-resolver.cjs +311 -0
- package/scripts/validate-frontmatter.ts +297 -2
- package/skills/peer-cli-add/SKILL.md +170 -0
- package/skills/peer-cli-customize/SKILL.md +110 -0
- package/skills/peers/SKILL.md +101 -0
- package/skills/router/SKILL.md +51 -2
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* bandit-router.cjs — contextual Thompson-sampling bandit over
|
|
3
|
-
* (agent_type, touches_size_bin) → {haiku, sonnet, opus}
|
|
3
|
+
* (agent_type, touches_size_bin[, delegate]) → {haiku, sonnet, opus}
|
|
4
|
+
* (Plan 23.5-01 + Plan 27-07 delegate dimension).
|
|
4
5
|
*
|
|
5
6
|
* Replaces Phase 10.1's static tier_overrides map when the user opts
|
|
6
7
|
* into adaptive_mode = "full". The static map continues to apply when
|
|
@@ -10,12 +11,25 @@
|
|
|
10
11
|
* .design/telemetry/posterior.json
|
|
11
12
|
* { schema_version: '1.0.0',
|
|
12
13
|
* generated_at: ISO,
|
|
13
|
-
* arms: [{agent, bin, tier, alpha, beta, last_used, count}] }
|
|
14
|
+
* arms: [{agent, bin, tier, delegate?, alpha, beta, last_used, count}] }
|
|
15
|
+
*
|
|
16
|
+
* The `delegate` field on an arm is OPTIONAL (Plan 27-07 / D-08). Existing
|
|
17
|
+
* callers that pass only `(agent, bin)` continue to read/write arms with
|
|
18
|
+
* `delegate === undefined`, which behaves identically to delegate='none'
|
|
19
|
+
* (i.e., the local-call slice). New callers can opt into the delegate
|
|
20
|
+
* dimension via `pullWithDelegate()` / `updateWithDelegate()` which
|
|
21
|
+
* persist `delegate ∈ {none, gemini, codex, cursor, copilot, qwen}`.
|
|
22
|
+
*
|
|
23
|
+
* Bootstrap discipline (D-08):
|
|
24
|
+
* - delegate='none' arms inherit Phase 23.5's TIER_PRIOR (informed).
|
|
25
|
+
* - delegate ∈ {gemini, codex, cursor, copilot, qwen} arms start
|
|
26
|
+
* neutral — the same TIER_PRIOR shape, on the assumption that we
|
|
27
|
+
* have no prior to favour any delegate over local; data drives.
|
|
14
28
|
*
|
|
15
29
|
* Atomic .tmp + rename. Discounted Thompson via per-arm time-decay
|
|
16
30
|
* factor `rho^days_since_last_use` applied at sample time, not stored.
|
|
17
31
|
*
|
|
18
|
-
* Reward computation (D-06): two-stage lexicographic
|
|
32
|
+
* Reward computation (D-06): two-stage lexicographic — UNCHANGED.
|
|
19
33
|
* if !solidify_pass: reward = 0
|
|
20
34
|
* elif user_undo_in_session: reward = 0
|
|
21
35
|
* else: reward = 1 - lambda * normalize(cost + epsilon * wall_time)
|
|
@@ -45,11 +59,25 @@ const TIER_PRIOR = Object.freeze({
|
|
|
45
59
|
const PRIOR_STRENGTH = 10;
|
|
46
60
|
const DEFAULT_TIERS = Object.freeze(['haiku', 'sonnet', 'opus']);
|
|
47
61
|
|
|
62
|
+
// Plan 27-07 / D-08. Delegate context dimension. 'none' = local Anthropic
|
|
63
|
+
// call; the other 5 are peer-CLI delegations via ACP/ASP. Adding this as
|
|
64
|
+
// a third context dimension expands the arm space 6× (78 → ~468 contexts).
|
|
65
|
+
const DELEGATE_NONE = 'none';
|
|
66
|
+
const DEFAULT_DELEGATES = Object.freeze([
|
|
67
|
+
DELEGATE_NONE,
|
|
68
|
+
'gemini',
|
|
69
|
+
'codex',
|
|
70
|
+
'cursor',
|
|
71
|
+
'copilot',
|
|
72
|
+
'qwen',
|
|
73
|
+
]);
|
|
74
|
+
|
|
48
75
|
const DEFAULT_PRIORS = Object.freeze({
|
|
49
76
|
decay: DEFAULT_DECAY,
|
|
50
77
|
strength: PRIOR_STRENGTH,
|
|
51
78
|
tiers: DEFAULT_TIERS,
|
|
52
79
|
perTier: TIER_PRIOR,
|
|
80
|
+
delegates: DEFAULT_DELEGATES,
|
|
53
81
|
});
|
|
54
82
|
|
|
55
83
|
const TOUCHES_BINS = Object.freeze([
|
|
@@ -141,12 +169,47 @@ function priorFor(tier, strength) {
|
|
|
141
169
|
};
|
|
142
170
|
}
|
|
143
171
|
|
|
144
|
-
|
|
145
|
-
|
|
172
|
+
/**
|
|
173
|
+
* @param {object[]} arms
|
|
174
|
+
* @param {string} agent
|
|
175
|
+
* @param {string} bin
|
|
176
|
+
* @param {string} tier
|
|
177
|
+
* @param {string} [delegate] — when provided, match arms with that
|
|
178
|
+
* delegate label. When omitted, match arms with no delegate field
|
|
179
|
+
* (legacy Phase 23.5 slice — equivalent to delegate='none' for
|
|
180
|
+
* bootstrap purposes but persisted distinctly to preserve
|
|
181
|
+
* round-trippability of existing posterior files).
|
|
182
|
+
*/
|
|
183
|
+
function findArm(arms, agent, bin, tier, delegate) {
|
|
184
|
+
if (delegate === undefined) {
|
|
185
|
+
return arms.find(
|
|
186
|
+
(a) =>
|
|
187
|
+
a.agent === agent &&
|
|
188
|
+
a.bin === bin &&
|
|
189
|
+
a.tier === tier &&
|
|
190
|
+
a.delegate === undefined,
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
return arms.find(
|
|
194
|
+
(a) =>
|
|
195
|
+
a.agent === agent &&
|
|
196
|
+
a.bin === bin &&
|
|
197
|
+
a.tier === tier &&
|
|
198
|
+
a.delegate === delegate,
|
|
199
|
+
);
|
|
146
200
|
}
|
|
147
201
|
|
|
148
|
-
|
|
149
|
-
|
|
202
|
+
/**
|
|
203
|
+
* Ensure an arm exists, creating it with the informed prior when missing.
|
|
204
|
+
*
|
|
205
|
+
* For Plan 27-07: when `delegate` is provided, the arm is persisted with
|
|
206
|
+
* that label. Bootstrap is identical for delegate='none' (inherits Phase
|
|
207
|
+
* 23.5 prior — no migration needed because the legacy slice and the
|
|
208
|
+
* 'none' slice are independent contexts) and for the 5 peer delegates
|
|
209
|
+
* (each starts neutral with the same TIER_PRIOR shape; data drives).
|
|
210
|
+
*/
|
|
211
|
+
function ensureArm(posterior, agent, bin, tier, strength, delegate) {
|
|
212
|
+
let arm = findArm(posterior.arms, agent, bin, tier, delegate);
|
|
150
213
|
if (arm) return arm;
|
|
151
214
|
const { alpha, beta } = priorFor(tier, strength);
|
|
152
215
|
arm = {
|
|
@@ -158,6 +221,9 @@ function ensureArm(posterior, agent, bin, tier, strength) {
|
|
|
158
221
|
last_used: null,
|
|
159
222
|
count: 0,
|
|
160
223
|
};
|
|
224
|
+
if (delegate !== undefined) {
|
|
225
|
+
arm.delegate = delegate;
|
|
226
|
+
}
|
|
161
227
|
posterior.arms.push(arm);
|
|
162
228
|
return arm;
|
|
163
229
|
}
|
|
@@ -310,6 +376,143 @@ function update(input) {
|
|
|
310
376
|
return { alpha: arm.alpha, beta: arm.beta, posteriorPath: p };
|
|
311
377
|
}
|
|
312
378
|
|
|
379
|
+
/**
|
|
380
|
+
* Pull an arm with the delegate context dimension (Plan 27-07 / D-08).
|
|
381
|
+
*
|
|
382
|
+
* Joint sample over `tiers × delegates` — i.e., 3 × 6 = 18 arms in the
|
|
383
|
+
* default case. Returns the (tier, delegate) pair with the highest
|
|
384
|
+
* sampled posterior. Bumps the chosen arm's last_used + count.
|
|
385
|
+
*
|
|
386
|
+
* Caller-restricted delegate set:
|
|
387
|
+
* - For `delegate_to: none` agents (Plan 27-06 frontmatter), the caller
|
|
388
|
+
* should pass `delegates: ['none']` to constrain sampling to the
|
|
389
|
+
* local-call slice — the bandit will not explore peer delegations.
|
|
390
|
+
* - For agents without `delegate_to` (default), the caller may either
|
|
391
|
+
* omit delegates (legacy `pull()` behaviour) or pass DEFAULT_DELEGATES
|
|
392
|
+
* to enable adaptive routing across the full 18-arm space.
|
|
393
|
+
*
|
|
394
|
+
* @param {{
|
|
395
|
+
* agent: string,
|
|
396
|
+
* bin: string,
|
|
397
|
+
* tiers?: string[],
|
|
398
|
+
* delegates?: string[],
|
|
399
|
+
* baseDir?: string,
|
|
400
|
+
* posteriorPath?: string,
|
|
401
|
+
* decay?: number,
|
|
402
|
+
* strength?: number,
|
|
403
|
+
* now?: Date,
|
|
404
|
+
* }} input
|
|
405
|
+
* @returns {{
|
|
406
|
+
* tier: string,
|
|
407
|
+
* delegate: string,
|
|
408
|
+
* samples: Record<string, Record<string, number>>,
|
|
409
|
+
* posteriorPath: string,
|
|
410
|
+
* }}
|
|
411
|
+
*/
|
|
412
|
+
function pullWithDelegate(input) {
|
|
413
|
+
if (!input || typeof input.agent !== 'string' || input.agent.length === 0) {
|
|
414
|
+
throw new TypeError('bandit-router.pullWithDelegate: agent (string) required');
|
|
415
|
+
}
|
|
416
|
+
if (typeof input.bin !== 'string' || input.bin.length === 0) {
|
|
417
|
+
throw new TypeError('bandit-router.pullWithDelegate: bin (string) required');
|
|
418
|
+
}
|
|
419
|
+
const tiers = input.tiers ?? DEFAULT_TIERS;
|
|
420
|
+
const delegates = input.delegates ?? DEFAULT_DELEGATES;
|
|
421
|
+
if (!Array.isArray(delegates) || delegates.length === 0) {
|
|
422
|
+
throw new TypeError(
|
|
423
|
+
'bandit-router.pullWithDelegate: delegates must be a non-empty array',
|
|
424
|
+
);
|
|
425
|
+
}
|
|
426
|
+
const strength = input.strength ?? PRIOR_STRENGTH;
|
|
427
|
+
const now = input.now ?? new Date();
|
|
428
|
+
|
|
429
|
+
const posterior = loadPosterior(input);
|
|
430
|
+
/** @type {Record<string, Record<string, number>>} */
|
|
431
|
+
const samples = {};
|
|
432
|
+
let bestTier = tiers[0];
|
|
433
|
+
let bestDelegate = delegates[0];
|
|
434
|
+
let bestSample = -1;
|
|
435
|
+
for (const delegate of delegates) {
|
|
436
|
+
samples[delegate] = {};
|
|
437
|
+
for (const tier of tiers) {
|
|
438
|
+
const arm = ensureArm(posterior, input.agent, input.bin, tier, strength, delegate);
|
|
439
|
+
const decayed = decayArm(arm, { decay: input.decay, now, strength });
|
|
440
|
+
const s = sampleBeta(decayed.alpha, decayed.beta);
|
|
441
|
+
samples[delegate][tier] = s;
|
|
442
|
+
if (s > bestSample) {
|
|
443
|
+
bestSample = s;
|
|
444
|
+
bestTier = tier;
|
|
445
|
+
bestDelegate = delegate;
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
const chosen = ensureArm(
|
|
450
|
+
posterior,
|
|
451
|
+
input.agent,
|
|
452
|
+
input.bin,
|
|
453
|
+
bestTier,
|
|
454
|
+
strength,
|
|
455
|
+
bestDelegate,
|
|
456
|
+
);
|
|
457
|
+
chosen.last_used = now.toISOString();
|
|
458
|
+
chosen.count += 1;
|
|
459
|
+
const written = savePosterior(posterior, input);
|
|
460
|
+
return {
|
|
461
|
+
tier: bestTier,
|
|
462
|
+
delegate: bestDelegate,
|
|
463
|
+
samples,
|
|
464
|
+
posteriorPath: written,
|
|
465
|
+
};
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
/**
|
|
469
|
+
* Update the posterior with a reward signal — delegate-aware variant.
|
|
470
|
+
*
|
|
471
|
+
* Reward signal is UNCHANGED from Phase 23.5 (D-08): two-stage
|
|
472
|
+
* lexicographic via `computeReward()` — correctness first, cost as
|
|
473
|
+
* tiebreaker. The delegate dimension is applied at the arm-locator
|
|
474
|
+
* level, not the reward computation.
|
|
475
|
+
*
|
|
476
|
+
* @param {{
|
|
477
|
+
* agent: string,
|
|
478
|
+
* bin: string,
|
|
479
|
+
* tier: string,
|
|
480
|
+
* delegate: string,
|
|
481
|
+
* reward: number,
|
|
482
|
+
* baseDir?: string,
|
|
483
|
+
* posteriorPath?: string,
|
|
484
|
+
* strength?: number,
|
|
485
|
+
* }} input
|
|
486
|
+
* @returns {{alpha: number, beta: number, posteriorPath: string}}
|
|
487
|
+
*/
|
|
488
|
+
function updateWithDelegate(input) {
|
|
489
|
+
if (!input) throw new TypeError('bandit-router.updateWithDelegate: input required');
|
|
490
|
+
for (const k of ['agent', 'bin', 'tier', 'delegate']) {
|
|
491
|
+
if (typeof input[k] !== 'string' || input[k].length === 0) {
|
|
492
|
+
throw new TypeError(
|
|
493
|
+
`bandit-router.updateWithDelegate: ${k} (string) required`,
|
|
494
|
+
);
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
if (typeof input.reward !== 'number' || Number.isNaN(input.reward)) {
|
|
498
|
+
throw new TypeError('bandit-router.updateWithDelegate: reward (number) required');
|
|
499
|
+
}
|
|
500
|
+
const r = Math.min(1, Math.max(0, input.reward));
|
|
501
|
+
const posterior = loadPosterior(input);
|
|
502
|
+
const arm = ensureArm(
|
|
503
|
+
posterior,
|
|
504
|
+
input.agent,
|
|
505
|
+
input.bin,
|
|
506
|
+
input.tier,
|
|
507
|
+
input.strength ?? PRIOR_STRENGTH,
|
|
508
|
+
input.delegate,
|
|
509
|
+
);
|
|
510
|
+
arm.alpha += r;
|
|
511
|
+
arm.beta += 1 - r;
|
|
512
|
+
const p = savePosterior(posterior, input);
|
|
513
|
+
return { alpha: arm.alpha, beta: arm.beta, posteriorPath: p };
|
|
514
|
+
}
|
|
515
|
+
|
|
313
516
|
/**
|
|
314
517
|
* Two-stage lexicographic reward (D-06).
|
|
315
518
|
*
|
|
@@ -350,6 +553,8 @@ function computeReward(input) {
|
|
|
350
553
|
module.exports = {
|
|
351
554
|
pull,
|
|
352
555
|
update,
|
|
556
|
+
pullWithDelegate,
|
|
557
|
+
updateWithDelegate,
|
|
353
558
|
reset,
|
|
354
559
|
loadPosterior,
|
|
355
560
|
savePosterior,
|
|
@@ -360,6 +565,8 @@ module.exports = {
|
|
|
360
565
|
priorFor,
|
|
361
566
|
DEFAULT_PRIORS,
|
|
362
567
|
DEFAULT_TIERS,
|
|
568
|
+
DEFAULT_DELEGATES,
|
|
569
|
+
DELEGATE_NONE,
|
|
363
570
|
TIER_PRIOR,
|
|
364
571
|
PRIOR_STRENGTH,
|
|
365
572
|
TOUCHES_BINS,
|