@tangle-network/starter-foundry 0.5.2 → 0.5.4

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 (121) hide show
  1. package/README.md +49 -0
  2. package/corpus/ideasai-prompts.json +119 -58
  3. package/dist/cli.js +28 -2
  4. package/dist/cli.js.map +1 -1
  5. package/dist/lib/agent-context.js +34 -22
  6. package/dist/lib/agent-context.js.map +1 -1
  7. package/dist/lib/build-plan.d.ts +18 -0
  8. package/dist/lib/build-plan.js +72 -0
  9. package/dist/lib/build-plan.js.map +1 -1
  10. package/dist/lib/buildout-traces.d.ts +113 -0
  11. package/dist/lib/buildout-traces.js +83 -0
  12. package/dist/lib/buildout-traces.js.map +1 -0
  13. package/dist/lib/capability-inferrer.d.ts +40 -0
  14. package/dist/lib/capability-inferrer.js +82 -0
  15. package/dist/lib/capability-inferrer.js.map +1 -0
  16. package/dist/lib/context-pack.d.ts +6 -1
  17. package/dist/lib/context-pack.js +9 -3
  18. package/dist/lib/context-pack.js.map +1 -1
  19. package/dist/lib/keywords.js +71 -18
  20. package/dist/lib/keywords.js.map +1 -1
  21. package/dist/lib/llm.d.ts +9 -0
  22. package/dist/lib/llm.js +70 -0
  23. package/dist/lib/llm.js.map +1 -0
  24. package/dist/lib/planner/contracts.d.ts +11 -0
  25. package/dist/lib/planner/contracts.js +119 -0
  26. package/dist/lib/planner/contracts.js.map +1 -0
  27. package/dist/lib/planner/detectors.d.ts +14 -0
  28. package/dist/lib/planner/detectors.js +195 -0
  29. package/dist/lib/planner/detectors.js.map +1 -0
  30. package/dist/lib/planner/helpers.d.ts +2 -0
  31. package/dist/lib/planner/helpers.js +135 -0
  32. package/dist/lib/planner/helpers.js.map +1 -0
  33. package/dist/lib/planner/implicit-caps.d.ts +1 -0
  34. package/dist/lib/planner/implicit-caps.js +91 -0
  35. package/dist/lib/planner/implicit-caps.js.map +1 -0
  36. package/dist/lib/planner/projects.d.ts +13 -0
  37. package/dist/lib/planner/projects.js +181 -0
  38. package/dist/lib/planner/projects.js.map +1 -0
  39. package/dist/lib/planner/signals.d.ts +17 -0
  40. package/dist/lib/planner/signals.js +324 -0
  41. package/dist/lib/planner/signals.js.map +1 -0
  42. package/dist/lib/product-brief.d.ts +25 -0
  43. package/dist/lib/product-brief.js +129 -0
  44. package/dist/lib/product-brief.js.map +1 -0
  45. package/dist/lib/prompt-planner.d.ts +5 -1
  46. package/dist/lib/prompt-planner.js +59 -622
  47. package/dist/lib/prompt-planner.js.map +1 -1
  48. package/dist/lib/prompt-rewriter.d.ts +21 -0
  49. package/dist/lib/prompt-rewriter.js +118 -0
  50. package/dist/lib/prompt-rewriter.js.map +1 -0
  51. package/dist/lib/selection.js +170 -36
  52. package/dist/lib/selection.js.map +1 -1
  53. package/dist/lib/telemetry.d.ts +0 -11
  54. package/dist/lib/telemetry.js +3 -3
  55. package/dist/lib/telemetry.js.map +1 -1
  56. package/dist/lib/vb-outcomes.d.ts +61 -0
  57. package/dist/lib/vb-outcomes.js +88 -0
  58. package/dist/lib/vb-outcomes.js.map +1 -0
  59. package/dist/training/variant_b/brief-loader.d.ts +5 -0
  60. package/dist/training/variant_b/brief-loader.js +263 -0
  61. package/dist/training/variant_b/brief-loader.js.map +1 -0
  62. package/dist/training/variant_b/flow.d.ts +56 -0
  63. package/dist/training/variant_b/flow.js +80 -0
  64. package/dist/training/variant_b/flow.js.map +1 -0
  65. package/dist/training/variant_b/generate.d.ts +7 -0
  66. package/dist/training/variant_b/generate.js +70 -0
  67. package/dist/training/variant_b/generate.js.map +1 -0
  68. package/dist/training/variant_b/judge.d.ts +8 -0
  69. package/dist/training/variant_b/judge.js +24 -0
  70. package/dist/training/variant_b/judge.js.map +1 -0
  71. package/dist/training/variant_b/nodes/collect.d.ts +31 -0
  72. package/dist/training/variant_b/nodes/collect.js +122 -0
  73. package/dist/training/variant_b/nodes/collect.js.map +1 -0
  74. package/dist/training/variant_b/nodes/generate.d.ts +22 -0
  75. package/dist/training/variant_b/nodes/generate.js +171 -0
  76. package/dist/training/variant_b/nodes/generate.js.map +1 -0
  77. package/dist/training/variant_b/nodes/judge.d.ts +26 -0
  78. package/dist/training/variant_b/nodes/judge.js +64 -0
  79. package/dist/training/variant_b/nodes/judge.js.map +1 -0
  80. package/dist/training/variant_b/nodes/promote.d.ts +15 -0
  81. package/dist/training/variant_b/nodes/promote.js +64 -0
  82. package/dist/training/variant_b/nodes/promote.js.map +1 -0
  83. package/dist/training/variant_b/nodes/rank.d.ts +12 -0
  84. package/dist/training/variant_b/nodes/rank.js +46 -0
  85. package/dist/training/variant_b/nodes/rank.js.map +1 -0
  86. package/dist/training/variant_b/nodes/train.d.ts +34 -0
  87. package/dist/training/variant_b/nodes/train.js +209 -0
  88. package/dist/training/variant_b/nodes/train.js.map +1 -0
  89. package/dist/training/variant_b/run-flow.d.ts +11 -0
  90. package/dist/training/variant_b/run-flow.js +21 -0
  91. package/dist/training/variant_b/run-flow.js.map +1 -0
  92. package/dist/training/variant_b/train.d.ts +15 -0
  93. package/dist/training/variant_b/train.js +37 -0
  94. package/dist/training/variant_b/train.js.map +1 -0
  95. package/dist/types.d.ts +16 -0
  96. package/package.json +6 -2
  97. package/registry/families/browser-extension-ts/files/package.json +4 -1
  98. package/registry/families/cli-ts/files/package.json +5 -0
  99. package/registry/families/electron-desktop-ts/files/package.json +3 -1
  100. package/registry/families/expo-react-native-ts/files/package.json +4 -0
  101. package/registry/families/fhenix-contracts/files/package.json +1 -1
  102. package/registry/families/fhevm-contracts/files/package.json +1 -1
  103. package/registry/families/fullstack-ts/files/package.json +3 -1
  104. package/registry/families/hardhat-contracts/files/package.json +3 -1
  105. package/registry/families/nextjs-ts/files/package.json +3 -1
  106. package/registry/families/react-vite-ts/files/package.json +11 -1
  107. package/registry/families/react-vite-ts/files/src/components/ui/badge.tsx +9 -0
  108. package/registry/families/react-vite-ts/files/src/components/ui/button.tsx +18 -0
  109. package/registry/families/react-vite-ts/files/src/components/ui/card.tsx +22 -0
  110. package/registry/families/react-vite-ts/manifest.json +14 -2
  111. package/registry/families/remix-ts/files/package.json +9 -1
  112. package/registry/families/sveltekit-ts/files/package.json +9 -1
  113. package/registry/families/tauri-desktop/files/package.json +3 -1
  114. package/registry/families/vue-ts/files/package.json +9 -1
  115. package/registry/layers/framework/expo-react-native-ts/files/tsconfig.json +2 -1
  116. package/registry/layers/framework/forge-foundation/files/foundry.toml +22 -1
  117. package/registry/layers/framework/fullstack-node-ts/files/personalize.json +5 -5
  118. package/registry/layers/framework/tangle-blueprint/files/TOOLCHAIN.md +16 -0
  119. package/registry/layers/framework/tangle-blueprint/files/rust-toolchain.toml +1 -1
  120. package/registry/layers/framework/tangle-blueprint/manifest.json +4 -0
  121. package/registry/package-to-capability.json +57 -0
@@ -0,0 +1,70 @@
1
+ // Public entrypoint: generateIdeas({ registryRoot, tracesPath })
2
+ //
3
+ // Scans the traces directory for the most recent trace file, rehydrates
4
+ // Trace[] from it, then invokes the generate node. The scripts/multi-pursue-eval.mjs
5
+ // harness calls this and feeds the result into judge.scoreCandidate.
6
+ import { readdir, readFile } from 'node:fs/promises';
7
+ import path from 'node:path';
8
+ import { createLLM, isLLMAvailable } from '../../lib/llm.js';
9
+ import { generateNode } from './nodes/generate.js';
10
+ async function loadLatestTraces(tracesDir) {
11
+ let files = [];
12
+ try {
13
+ files = (await readdir(tracesDir)).filter((f) => f.startsWith('variant_b-') && f.endsWith('.jsonl')).sort();
14
+ }
15
+ catch {
16
+ return [];
17
+ }
18
+ if (files.length === 0)
19
+ return [];
20
+ const latest = files[files.length - 1];
21
+ const raw = await readFile(path.join(tracesDir, latest), 'utf8');
22
+ const traces = [];
23
+ for (const line of raw.split('\n')) {
24
+ const trimmed = line.trim();
25
+ if (!trimmed)
26
+ continue;
27
+ try {
28
+ traces.push(JSON.parse(trimmed));
29
+ }
30
+ catch {
31
+ // skip malformed lines
32
+ }
33
+ }
34
+ return traces;
35
+ }
36
+ export async function generateIdeas(input) {
37
+ const traces = await loadLatestTraces(input.tracesPath);
38
+ // Create an LLM only if we can — the mine-from-traces path runs anyway.
39
+ let llm;
40
+ try {
41
+ llm = isLLMAvailable() ? createLLM() : undefined;
42
+ }
43
+ catch {
44
+ llm = undefined;
45
+ }
46
+ if (!llm) {
47
+ // Use a fake AxAIService-compatible shim only for mined candidates. Node
48
+ // handles the llm-undefined branch internally when proposerAgent fails.
49
+ // Easier: pass a harmless throw to skip LLM path.
50
+ const throwing = {
51
+ async chat() { throw new Error('no-llm'); },
52
+ getId: () => 'noop',
53
+ };
54
+ const out = await generateNode({
55
+ registryRoot: input.registryRoot,
56
+ traces,
57
+ llm: throwing,
58
+ maxCandidates: input.maxCandidates,
59
+ });
60
+ return out.candidates;
61
+ }
62
+ const out = await generateNode({
63
+ registryRoot: input.registryRoot,
64
+ traces,
65
+ llm,
66
+ maxCandidates: input.maxCandidates,
67
+ });
68
+ return out.candidates;
69
+ }
70
+ //# sourceMappingURL=generate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate.js","sourceRoot":"","sources":["../../../src/training/variant_b/generate.ts"],"names":[],"mappings":"AAAA,iEAAiE;AACjE,EAAE;AACF,wEAAwE;AACxE,qFAAqF;AACrF,qEAAqE;AAErE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AACpD,OAAO,IAAI,MAAM,WAAW,CAAA;AAC5B,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAUlD,KAAK,UAAU,gBAAgB,CAAC,SAAiB;IAC/C,IAAI,KAAK,GAAa,EAAE,CAAA;IACxB,IAAI,CAAC;QACH,KAAK,GAAG,CAAC,MAAM,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,EAAE,CAAA;IAC7G,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAA;IACX,CAAC;IACD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAA;IACjC,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAE,CAAA;IACvC,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,CAAA;IAChE,MAAM,MAAM,GAAY,EAAE,CAAA;IAC1B,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACnC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAA;QAC3B,IAAI,CAAC,OAAO;YAAE,SAAQ;QACtB,IAAI,CAAC;YACH,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAU,CAAC,CAAA;QAC3C,CAAC;QAAC,MAAM,CAAC;YACP,uBAAuB;QACzB,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAA;AACf,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,KAAyB;IAC3D,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC,KAAK,CAAC,UAAU,CAAC,CAAA;IACvD,wEAAwE;IACxE,IAAI,GAAG,CAAA;IACP,IAAI,CAAC;QACH,GAAG,GAAG,cAAc,EAAE,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,SAAS,CAAA;IAClD,CAAC;IAAC,MAAM,CAAC;QACP,GAAG,GAAG,SAAS,CAAA;IACjB,CAAC;IACD,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,yEAAyE;QACzE,wEAAwE;QACxE,kDAAkD;QAClD,MAAM,QAAQ,GAAG;YACf,KAAK,CAAC,IAAI,KAAK,MAAM,IAAI,KAAK,CAAC,QAAQ,CAAC,CAAA,CAAC,CAAC;YAC1C,KAAK,EAAE,GAAG,EAAE,CAAC,MAAM;SACoC,CAAA;QACzD,MAAM,GAAG,GAAG,MAAM,YAAY,CAAC;YAC7B,YAAY,EAAE,KAAK,CAAC,YAAY;YAChC,MAAM;YACN,GAAG,EAAE,QAAQ;YACb,aAAa,EAAE,KAAK,CAAC,aAAa;SACnC,CAAC,CAAA;QACF,OAAO,GAAG,CAAC,UAAU,CAAA;IACvB,CAAC;IACD,MAAM,GAAG,GAAG,MAAM,YAAY,CAAC;QAC7B,YAAY,EAAE,KAAK,CAAC,YAAY;QAChC,MAAM;QACN,GAAG;QACH,aAAa,EAAE,KAAK,CAAC,aAAa;KACnC,CAAC,CAAA;IACF,OAAO,GAAG,CAAC,UAAU,CAAA;AACvB,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { CandidateScore } from './nodes/judge.js';
2
+ import type { ArchetypeCandidate } from './nodes/generate.js';
3
+ export interface ScoreCandidateInput {
4
+ spec: ArchetypeCandidate;
5
+ }
6
+ export interface ScoreCandidateResult extends CandidateScore {
7
+ }
8
+ export declare function scoreCandidate(input: ScoreCandidateInput): Promise<ScoreCandidateResult>;
@@ -0,0 +1,24 @@
1
+ // Public entrypoint: scoreCandidate({ spec })
2
+ //
3
+ // The multi-pursue harness iterates candidates from generateIdeas and calls
4
+ // scoreCandidate on each. Returns the judge's composite score + promotable
5
+ // flag. LLM is used when available; deterministic scoring is the fallback.
6
+ import { createLLM, isLLMAvailable } from '../../lib/llm.js';
7
+ import { judgeNode } from './nodes/judge.js';
8
+ export async function scoreCandidate(input) {
9
+ let llm;
10
+ try {
11
+ llm = isLLMAvailable() ? createLLM() : undefined;
12
+ }
13
+ catch {
14
+ llm = undefined;
15
+ }
16
+ const out = await judgeNode({
17
+ candidates: [input.spec],
18
+ judgePath: '.evolve/judge/variant_b.jsonl',
19
+ llm,
20
+ useLLM: llm !== undefined,
21
+ });
22
+ return out.scored[0].score;
23
+ }
24
+ //# sourceMappingURL=judge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"judge.js","sourceRoot":"","sources":["../../../src/training/variant_b/judge.ts"],"names":[],"mappings":"AAAA,8CAA8C;AAC9C,EAAE;AACF,4EAA4E;AAC5E,2EAA2E;AAC3E,2EAA2E;AAE3E,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAC5D,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAU5C,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,KAA0B;IAC7D,IAAI,GAAG,CAAA;IACP,IAAI,CAAC;QACH,GAAG,GAAG,cAAc,EAAE,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,SAAS,CAAA;IAClD,CAAC;IAAC,MAAM,CAAC;QACP,GAAG,GAAG,SAAS,CAAA;IACjB,CAAC;IACD,MAAM,GAAG,GAAG,MAAM,SAAS,CAAC;QAC1B,UAAU,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC;QACxB,SAAS,EAAE,+BAA+B;QAC1C,GAAG;QACH,MAAM,EAAE,GAAG,KAAK,SAAS;KAC1B,CAAC,CAAA;IACF,OAAO,GAAG,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC,KAAK,CAAA;AAC7B,CAAC"}
@@ -0,0 +1,31 @@
1
+ export interface Trace {
2
+ scenarioId: string;
3
+ corpus: 'ideasai' | 'held-out';
4
+ prompt: string;
5
+ partner: string | null;
6
+ expectedFamily: string | null;
7
+ expectedCapabilities: string[];
8
+ actualFamily: string | null;
9
+ actualCapabilities: string[];
10
+ kindMatch: boolean;
11
+ familyMatch: boolean;
12
+ capabilityHit: number;
13
+ latencyMs: number;
14
+ error: string | null;
15
+ timestamp: string;
16
+ }
17
+ export interface CollectInput {
18
+ corpusPath: string;
19
+ tracesDir: string;
20
+ limit?: number;
21
+ includeHeldOut?: boolean;
22
+ }
23
+ export interface CollectOutput {
24
+ traces: Trace[];
25
+ tracesFile: string;
26
+ coverageGaps: Array<{
27
+ capability: string;
28
+ missCount: number;
29
+ }>;
30
+ }
31
+ export declare function collectNode(input: CollectInput): Promise<CollectOutput>;
@@ -0,0 +1,122 @@
1
+ // collect node: reads ideasai + held-out corpora, runs the current planner on
2
+ // each prompt, and materializes a typed Trace per scenario. Traces are the
3
+ // only thing the train node reads — decoupling the corpus loader from the
4
+ // optimizer. A different collect implementation (live prod traffic, synthetic
5
+ // scenarios, etc.) can be swapped in without touching train.
6
+ import { readFile, mkdir, appendFile } from 'node:fs/promises';
7
+ import path from 'node:path';
8
+ import { performance } from 'node:perf_hooks';
9
+ import { planPrompt } from '../../../lib/prompt-planner.js';
10
+ function jaccard(a, b) {
11
+ const A = new Set(a);
12
+ const B = new Set(b);
13
+ if (A.size === 0 && B.size === 0)
14
+ return 1;
15
+ let inter = 0;
16
+ for (const x of A)
17
+ if (B.has(x))
18
+ inter++;
19
+ const union = A.size + B.size - inter;
20
+ return union === 0 ? 1 : inter / union;
21
+ }
22
+ function extractActual(plan) {
23
+ const p = plan;
24
+ if (!p)
25
+ return { kind: null, family: null, capabilities: [] };
26
+ if (p.kind === 'starter') {
27
+ return { kind: 'starter', family: p.spec?.family ?? null, capabilities: p.spec?.layers ?? [] };
28
+ }
29
+ if (p.kind === 'workspace') {
30
+ const caps = [];
31
+ for (const proj of p.spec?.projects ?? []) {
32
+ for (const layer of proj.layers ?? [])
33
+ caps.push(layer);
34
+ }
35
+ return { kind: 'workspace', family: 'workspace', capabilities: caps };
36
+ }
37
+ return { kind: p.kind ?? null, family: null, capabilities: [] };
38
+ }
39
+ export async function collectNode(input) {
40
+ const ideasRaw = await readFile(input.corpusPath, 'utf8');
41
+ const ideas = JSON.parse(ideasRaw);
42
+ const scenarios = [];
43
+ for (const s of ideas) {
44
+ scenarios.push({
45
+ id: s.id,
46
+ corpus: 'ideasai',
47
+ prompt: s.prompt,
48
+ partner: null,
49
+ expectedFamily: s.expectedFamily ?? null,
50
+ expectedCapabilities: s.expectedCapabilities ?? [],
51
+ });
52
+ }
53
+ if (input.includeHeldOut !== false) {
54
+ try {
55
+ const heldRaw = await readFile('corpus/held-out-validation.json', 'utf8');
56
+ const held = JSON.parse(heldRaw);
57
+ for (const s of held.scenarios) {
58
+ scenarios.push({
59
+ id: s.id,
60
+ corpus: 'held-out',
61
+ prompt: s.prompt,
62
+ partner: s.partner ?? null,
63
+ expectedFamily: s.expected?.family ?? null,
64
+ expectedCapabilities: s.expected?.capabilities ?? [],
65
+ });
66
+ }
67
+ }
68
+ catch {
69
+ // held-out missing is fine for unit tests
70
+ }
71
+ }
72
+ const limited = input.limit ? scenarios.slice(0, input.limit) : scenarios;
73
+ const traces = [];
74
+ const missPerCap = new Map();
75
+ await mkdir(input.tracesDir, { recursive: true });
76
+ const tracesFile = path.join(input.tracesDir, `variant_b-${Date.now()}.jsonl`);
77
+ for (const s of limited) {
78
+ const t0 = performance.now();
79
+ let plan = null;
80
+ let error = null;
81
+ try {
82
+ plan = await planPrompt({ prompt: s.prompt, partner: s.partner });
83
+ }
84
+ catch (err) {
85
+ error = err instanceof Error ? err.message : String(err);
86
+ }
87
+ const latencyMs = performance.now() - t0;
88
+ const actual = extractActual(plan);
89
+ const familyMatch = s.expectedFamily ? actual.family === s.expectedFamily : true;
90
+ const capabilityHit = s.expectedCapabilities.length
91
+ ? jaccard(actual.capabilities, s.expectedCapabilities)
92
+ : 1;
93
+ for (const cap of s.expectedCapabilities) {
94
+ if (!actual.capabilities.includes(cap)) {
95
+ missPerCap.set(cap, (missPerCap.get(cap) ?? 0) + 1);
96
+ }
97
+ }
98
+ const trace = {
99
+ scenarioId: s.id,
100
+ corpus: s.corpus,
101
+ prompt: s.prompt,
102
+ partner: s.partner,
103
+ expectedFamily: s.expectedFamily,
104
+ expectedCapabilities: s.expectedCapabilities,
105
+ actualFamily: actual.family,
106
+ actualCapabilities: actual.capabilities,
107
+ kindMatch: actual.kind !== null,
108
+ familyMatch,
109
+ capabilityHit,
110
+ latencyMs,
111
+ error,
112
+ timestamp: new Date().toISOString(),
113
+ };
114
+ traces.push(trace);
115
+ await appendFile(tracesFile, JSON.stringify(trace) + '\n');
116
+ }
117
+ const coverageGaps = [...missPerCap.entries()]
118
+ .map(([capability, missCount]) => ({ capability, missCount }))
119
+ .sort((a, b) => b.missCount - a.missCount);
120
+ return { traces, tracesFile, coverageGaps };
121
+ }
122
+ //# sourceMappingURL=collect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"collect.js","sourceRoot":"","sources":["../../../../src/training/variant_b/nodes/collect.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import type { AxAIService } from '@ax-llm/ax';
2
+ import type { Trace } from './collect.js';
3
+ export interface ArchetypeCandidate {
4
+ id: string;
5
+ description: string;
6
+ family: string;
7
+ capabilities: string[];
8
+ promptKeywords: string[];
9
+ rationale: string;
10
+ source: 'coverage-gap' | 'cooccurrence' | 'llm-proposed';
11
+ }
12
+ export interface GenerateInput {
13
+ registryRoot: string;
14
+ traces: Trace[];
15
+ llm: AxAIService;
16
+ maxCandidates?: number;
17
+ }
18
+ export interface GenerateOutput {
19
+ candidates: ArchetypeCandidate[];
20
+ existingArchetypes: string[];
21
+ }
22
+ export declare function generateNode(input: GenerateInput): Promise<GenerateOutput>;
@@ -0,0 +1,171 @@
1
+ // generate node: looks at coverage gaps in the traces + uncovered capability
2
+ // co-occurrences, then uses an ax program to propose new archetype definitions
3
+ // (capability bundles) that would plug the gaps. Output is candidates, not
4
+ // committed archetypes — the judge + rank + promote nodes decide what lands.
5
+ import { readFile, readdir } from 'node:fs/promises';
6
+ import path from 'node:path';
7
+ import { ax } from '@ax-llm/ax';
8
+ async function loadExistingArchetypes(registryRoot) {
9
+ try {
10
+ const dir = path.join(registryRoot, 'layers', 'capability');
11
+ const entries = await readdir(dir, { withFileTypes: true });
12
+ return entries.filter((e) => e.isDirectory()).map((e) => e.name);
13
+ }
14
+ catch {
15
+ return [];
16
+ }
17
+ }
18
+ async function loadCapabilityKeywords(registryRoot, existing) {
19
+ const out = new Map();
20
+ for (const id of existing) {
21
+ try {
22
+ const manifestPath = path.join(registryRoot, 'layers', 'capability', id, 'manifest.json');
23
+ const raw = await readFile(manifestPath, 'utf8');
24
+ const manifest = JSON.parse(raw);
25
+ out.set(id, manifest.keywords ?? []);
26
+ }
27
+ catch {
28
+ // skip
29
+ }
30
+ }
31
+ return out;
32
+ }
33
+ // Derive candidates from real data first. LLM proposal is layered on top —
34
+ // the judge will separate signal from slop.
35
+ function mineCandidatesFromTraces(traces, existingIds) {
36
+ const cooccur = new Map();
37
+ for (const t of traces) {
38
+ const caps = t.expectedCapabilities;
39
+ for (let i = 0; i < caps.length; i++) {
40
+ for (let j = i + 1; j < caps.length; j++) {
41
+ const a = caps[i];
42
+ const b = caps[j];
43
+ const key = a < b ? `${a}|${b}` : `${b}|${a}`;
44
+ const [l, r] = key.split('|');
45
+ if (!cooccur.has(l))
46
+ cooccur.set(l, new Map());
47
+ cooccur.get(l).set(r, (cooccur.get(l).get(r) ?? 0) + 1);
48
+ }
49
+ }
50
+ }
51
+ const bundles = [];
52
+ for (const [l, rs] of cooccur) {
53
+ for (const [r, count] of rs) {
54
+ if (count < 3)
55
+ continue;
56
+ const pairId = `${l.replace('capability:', '')}-${r.replace('capability:', '')}`;
57
+ const id = `bundle-${pairId}`;
58
+ if (existingIds.has(id))
59
+ continue;
60
+ const keywords = new Set();
61
+ for (const t of traces) {
62
+ if (t.expectedCapabilities.includes(l) && t.expectedCapabilities.includes(r)) {
63
+ for (const w of t.prompt.toLowerCase().split(/\W+/).filter((w) => w.length >= 4)) {
64
+ keywords.add(w);
65
+ }
66
+ }
67
+ }
68
+ bundles.push({
69
+ id,
70
+ description: `Bundle of ${l} + ${r} — co-occurs in ${count} training prompts.`,
71
+ family: 'fullstack-ts',
72
+ capabilities: [l, r],
73
+ promptKeywords: [...keywords].slice(0, 12),
74
+ rationale: `Co-occurrence count ${count} in ideasai corpus.`,
75
+ source: 'cooccurrence',
76
+ });
77
+ }
78
+ }
79
+ // Plus: each high-miss capability that's present in the corpus but missed
80
+ // in traces becomes a candidate archetype that binds the capability +
81
+ // its strongest partner capability.
82
+ const missByCap = new Map();
83
+ for (const t of traces) {
84
+ for (const cap of t.expectedCapabilities) {
85
+ if (!t.actualCapabilities.includes(cap)) {
86
+ missByCap.set(cap, (missByCap.get(cap) ?? 0) + 1);
87
+ }
88
+ }
89
+ }
90
+ const topMiss = [...missByCap.entries()].sort((a, b) => b[1] - a[1]).slice(0, 6);
91
+ for (const [cap, missCount] of topMiss) {
92
+ const id = `gap-${cap.replace('capability:', '')}`;
93
+ if (existingIds.has(id))
94
+ continue;
95
+ const keywords = new Set();
96
+ for (const t of traces) {
97
+ if (t.expectedCapabilities.includes(cap)) {
98
+ for (const w of t.prompt.toLowerCase().split(/\W+/).filter((w) => w.length >= 4)) {
99
+ keywords.add(w);
100
+ }
101
+ }
102
+ }
103
+ bundles.push({
104
+ id,
105
+ description: `Fill coverage gap for ${cap} — missed in ${missCount} training traces.`,
106
+ family: 'fullstack-ts',
107
+ capabilities: [cap],
108
+ promptKeywords: [...keywords].slice(0, 12),
109
+ rationale: `Top-N coverage gap (miss count ${missCount}).`,
110
+ source: 'coverage-gap',
111
+ });
112
+ }
113
+ return bundles;
114
+ }
115
+ // LLM-proposed archetype node: takes the top-N coverage gaps + a sample of
116
+ // prompts and asks for a structured archetype name + capability bundle that
117
+ // would plug the gaps. Kept narrow on purpose — judge & rank filter the noise.
118
+ const proposerAgent = ax('"Propose a new product archetype that would help route ambiguous AI-product prompts to the right capability bundle. The archetype id must be kebab-case. Capabilities must be drawn ONLY from knownCapabilities. Promptkeywords must be single tokens that actually appear in problemPrompts." ' +
119
+ 'coverageGaps:string[], problemPrompts:string[], knownCapabilities:string[] -> ' +
120
+ 'archetypeId:string, description:string, family:string, capabilities:string[], promptKeywords:string[], rationale:string');
121
+ export async function generateNode(input) {
122
+ const existing = await loadExistingArchetypes(input.registryRoot);
123
+ const existingSet = new Set(existing);
124
+ const capKeywords = await loadCapabilityKeywords(input.registryRoot, existing);
125
+ const knownCapabilities = [...capKeywords.keys()].map((id) => `capability:${id}`);
126
+ const mined = mineCandidatesFromTraces(input.traces, existingSet);
127
+ // LLM proposal: surface the worst-covered gaps + real prompts as context.
128
+ const missByCap = new Map();
129
+ for (const t of input.traces) {
130
+ for (const cap of t.expectedCapabilities) {
131
+ if (!t.actualCapabilities.includes(cap))
132
+ missByCap.set(cap, (missByCap.get(cap) ?? 0) + 1);
133
+ }
134
+ }
135
+ const topGaps = [...missByCap.entries()].sort((a, b) => b[1] - a[1]).slice(0, 5).map(([c]) => c);
136
+ const problemPrompts = input.traces
137
+ .filter((t) => t.capabilityHit < 0.5 && t.corpus === 'ideasai')
138
+ .slice(0, 8)
139
+ .map((t) => t.prompt);
140
+ const llmCandidates = [];
141
+ if (problemPrompts.length > 0 && topGaps.length > 0) {
142
+ try {
143
+ const raw = (await proposerAgent.forward(input.llm, {
144
+ coverageGaps: topGaps,
145
+ problemPrompts,
146
+ knownCapabilities,
147
+ }, { stream: false }));
148
+ if (raw.archetypeId && Array.isArray(raw.capabilities) && raw.capabilities.length > 0) {
149
+ const validCaps = raw.capabilities.filter((c) => knownCapabilities.includes(c));
150
+ if (validCaps.length > 0 && !existingSet.has(raw.archetypeId)) {
151
+ llmCandidates.push({
152
+ id: raw.archetypeId,
153
+ description: raw.description ?? '',
154
+ family: raw.family ?? 'fullstack-ts',
155
+ capabilities: validCaps,
156
+ promptKeywords: (raw.promptKeywords ?? []).filter((w) => typeof w === 'string' && w.length > 2),
157
+ rationale: raw.rationale ?? '',
158
+ source: 'llm-proposed',
159
+ });
160
+ }
161
+ }
162
+ }
163
+ catch {
164
+ // LLM proposal is optional — mined candidates carry the loop alone
165
+ }
166
+ }
167
+ const max = input.maxCandidates ?? 12;
168
+ const candidates = [...mined, ...llmCandidates].slice(0, max);
169
+ return { candidates, existingArchetypes: existing };
170
+ }
171
+ //# sourceMappingURL=generate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate.js","sourceRoot":"","sources":["../../../../src/training/variant_b/nodes/generate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ import type { AxAIService } from '@ax-llm/ax';
2
+ import type { ArchetypeCandidate } from './generate.js';
3
+ export interface CandidateScore {
4
+ utility: number;
5
+ specificity: number;
6
+ novelty: number;
7
+ rubric: number;
8
+ composite: number;
9
+ promotable: boolean;
10
+ notes: string;
11
+ }
12
+ export interface ScoredCandidate {
13
+ candidate: ArchetypeCandidate;
14
+ score: CandidateScore;
15
+ }
16
+ export interface JudgeInput {
17
+ candidates: ArchetypeCandidate[];
18
+ judgePath: string;
19
+ llm?: AxAIService;
20
+ useLLM?: boolean;
21
+ promoteThreshold?: number;
22
+ }
23
+ export interface JudgeOutput {
24
+ scored: ScoredCandidate[];
25
+ }
26
+ export declare function judgeNode(input: JudgeInput): Promise<JudgeOutput>;
@@ -0,0 +1,64 @@
1
+ // judge node: LLM-as-judge + deterministic checks. Each candidate archetype
2
+ // is scored on (a) coverage-gap-fit, (b) keyword specificity, (c) non-overlap
3
+ // with existing archetypes, (d) an LLM rubric score on "is this a real,
4
+ // useful archetype that future prompts would match".
5
+ //
6
+ // Swap strategy: replace the rubric signature with a different judge
7
+ // (pairwise preference, ensemble, rule-only) without changing the output
8
+ // contract.
9
+ import { appendFile, mkdir } from 'node:fs/promises';
10
+ import path from 'node:path';
11
+ import { ax } from '@ax-llm/ax';
12
+ const rubricAgent = ax('"Score an archetype candidate on four dimensions from 0.0 to 1.0. utility = how often future AI-saas prompts will match. specificity = how unique the keyword set is. novelty = how different from existing archetypes. overall = weighted sum. Return short reasoning." ' +
13
+ 'archetypeId:string, description:string, capabilities:string[], promptKeywords:string[], existingArchetypes:string[] -> ' +
14
+ 'utility:number, specificity:number, novelty:number, overall:number, reasoning:string');
15
+ function deterministicScore(c) {
16
+ const kw = c.promptKeywords ?? [];
17
+ const specificity = Math.min(1, kw.length / 8);
18
+ const utility = c.source === 'cooccurrence' ? 0.8 : c.source === 'coverage-gap' ? 0.7 : 0.5;
19
+ const novelty = c.capabilities.length >= 2 ? 0.8 : 0.5;
20
+ return { specificity, novelty, utility };
21
+ }
22
+ export async function judgeNode(input) {
23
+ const scored = [];
24
+ await mkdir(path.dirname(input.judgePath), { recursive: true });
25
+ const useLLM = input.useLLM !== false && input.llm !== undefined;
26
+ const promoteThreshold = input.promoteThreshold ?? 0.6;
27
+ for (const candidate of input.candidates) {
28
+ const det = deterministicScore(candidate);
29
+ let rubric = 0.5;
30
+ let notes = '';
31
+ if (useLLM && input.llm) {
32
+ try {
33
+ const raw = (await rubricAgent.forward(input.llm, {
34
+ archetypeId: candidate.id,
35
+ description: candidate.description,
36
+ capabilities: candidate.capabilities,
37
+ promptKeywords: candidate.promptKeywords,
38
+ existingArchetypes: [],
39
+ }, { stream: false }));
40
+ const overall = typeof raw.overall === 'number' ? raw.overall : 0.5;
41
+ rubric = Math.max(0, Math.min(1, overall));
42
+ notes = raw.reasoning ?? '';
43
+ }
44
+ catch {
45
+ // LLM blip — deterministic score carries
46
+ }
47
+ }
48
+ const composite = 0.25 * det.utility + 0.25 * det.specificity + 0.2 * det.novelty + 0.3 * rubric;
49
+ const promotable = composite >= promoteThreshold && candidate.capabilities.length > 0;
50
+ const score = {
51
+ utility: det.utility,
52
+ specificity: det.specificity,
53
+ novelty: det.novelty,
54
+ rubric,
55
+ composite,
56
+ promotable,
57
+ notes,
58
+ };
59
+ scored.push({ candidate, score });
60
+ await appendFile(input.judgePath, JSON.stringify({ candidate, score, timestamp: new Date().toISOString() }) + '\n');
61
+ }
62
+ return { scored };
63
+ }
64
+ //# sourceMappingURL=judge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"judge.js","sourceRoot":"","sources":["../../../../src/training/variant_b/nodes/judge.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import type { RankedCandidate } from './rank.js';
2
+ export interface PromoteInput {
3
+ ranked: RankedCandidate[];
4
+ registryRoot: string;
5
+ maxPromotions?: number;
6
+ dryRun?: boolean;
7
+ }
8
+ export interface PromoteOutput {
9
+ promoted: string[];
10
+ skipped: Array<{
11
+ id: string;
12
+ reason: string;
13
+ }>;
14
+ }
15
+ export declare function promoteNode(input: PromoteInput): Promise<PromoteOutput>;